Trouble with StringBuilder.Replace in 4.2 on Cobra I

I can’t get the StringBuilder Replace to work. Here is my simplified code:

[Code]
private static string segment = “1234567890”;
public static string oldValue = “—”;
public static string newValue = “======”;
public static string source = null;
public static string dest = null;

public static void Main()
{
Debug.EnableGCMessages(false);

StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10; i++)
{
	sb.Append(segment.Substring(0, i));
	sb.Append(oldValue);
}
source = sb.ToString();

TimeSpan startTime = new TimeSpan();
TimeSpan endTime = new TimeSpan();

Debug.Print("");
Debug.Print("Test 1: string replace using StringBuilder.Replace...");
sb.Clear();
sb = null;
dest = null;

Debug.GC(true);
Debug.Print("    Free mem before : " + Debug.GC(false).ToString());

startTime = Utility.GetMachineTime();

sb = new StringBuilder(source);
sb.Capacity = source.Length * 50;
sb.Length = source.Length * 50;
Debug.Print("    Capacity = " + sb.Capacity);
sb.Replace(oldValue, newValue);
dest = sb.ToString();

endTime = Utility.GetMachineTime();

Debug.Print("    Free mem after  : " + Debug.GC(false).ToString());
Debug.Print("    Elapsed msecs   : " + (((double)endTime.Subtract(startTime).Ticks) / ((double)TimeSpan.TicksPerMillisecond)).ToString());
Debug.Print("    Source string   : " + source);
Debug.Print("    Dest string     : " + dest);
Debug.Print("    Source length   : " + source.Length);
Debug.Print("    Dest length     : " + dest.Length);
Debug.Print("");

}
[/Code]

And here is a dump of the StringBuilder when it’s stopped in the debugger:

sb {1======12======123======1234======12345123—1234—12345—123456—1234567—12345678—123456789—1234567890—}
Capacity 4280
Length 4280
m_ChunkChars {char[4250]}
m_ChunkLength 4250
m_ChunkOffset 30
m_ChunkPrevious {1======12======123======1234==}
m_MaxCapacity 2147483647
MaxCapacity 2147483647

And here is the exception. It seems to indicate that the MaxCapacity is insufficient, but that can’t be true??

Test 1: string replace using StringBuilder.Replace…
Free mem before : 7288344
Capacity = 4250
#### Exception System.ArgumentOutOfRangeException - CLR_E_OUT_OF_RANGE (1) ####
#### Message:
#### System.Array::Copy [IP: 0000] ####
#### System.Text.StringBuilder::ReplaceInPlaceAtChunk [IP: 0022] ####
#### System.Text.StringBuilder::ReplaceAllInChunk [IP: 0047] ####
#### System.Text.StringBuilder::Replace [IP: 00e4] ####
#### System.Text.StringBuilder::Replace [IP: 000b] ####
#### FEZCobra.WebServer.ProgramTest::Main [IP: 00bf] ####
A first chance exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dll
An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dl

@ jasdev - We were able to reproduce this error with StringBuilder. You should report this bug to Microsoft, however if you need a string replace method in the mean time, you can use this:


string StringReplace(string token, string text, string haystack)
        {
            string left = "";
            string right = "";
            string buffer = haystack;
            int index = buffer.IndexOf(token);

            while (index >= 0)
            {
                int other_index = index + token.Length;

                left = buffer.Substring(0, index);
                right = buffer.Substring(other_index);
                buffer = left + text + right;

                index = buffer.IndexOf(token);
            }

            return buffer;
        }

Example usage:


string blah = "I am a string";
blah = StringReplace("am","am still",blah);
Debug.Print(blah);

Thanks guys. I created a new issue on CodePlex: http://netmf.codeplex.com/workitem/1858

@ Andre - I’m actually developing my own string Replace extension method that I hope will be faster and more memory-efficient than other managed solutions I’ve seen.

@ James - I will include your StringReplace in my tests. Thanks.

@ andre - Yes I know, but I want my libraries to be “platform” independent, so I don’t want to use RLP. Also, if I read your comments correctly, your solution requires that the user set the size of the byte array large enough to contain the resulting string. This is not possible in the situations where I want to use this function.

Your solution looks great, and is useable for most applications, but I wanted a more general solution that would work for large string arrays, and for strings that required an unknown number of tokens to be replaced.

I did a search on this forum, on the CodeShare site, and in Google for NETMF string Replace implementations. I found several including yours, but I only wanted to test managed solutions. I’m working on my own managed solution, and I wanted to test it against the solutions I found, and against the “native” StringBuilder Replace function. If my solution turns out to be faster and/or more memory-efficient than those I found, than I will publish it on CodeShare.