I distinctly remember from the early days of .NET that calling ToString on a StringBuilder used to provide the new string object (to be returned) with the internal char buffer used by StringBuilder. This way if you constructed a huge string using StringBuilder, calling ToString didn't have to copy it.
In doing that, the StringBuilder had to prevent any additional changes to the buffer, because it was now used by an immutable string. As a result the StringBuilder would switch to a "copy-on-change" made where any attempted change would first create a new buffer, copy the content of the old buffer to it and only then change it.
I think the assumption was that StringBuilder would be used to construct a string, then converted to a regular string and discarded. Seems like a reasonable assumption to me.
Now here is the thing. I can't find any mention of this in the documentation. But I'm not sure it was ever documented.
So I looked at the implementation of ToString using Reflector (.NET 4.0), and it seems to me that it actually copies the string, rather than just share the buffer:
[SecuritySafeCritical]
public override unsafe string ToString()
{
string str = string.FastAllocateString(this.Length);
StringBuilder chunkPrevious = this;
fixed (char* str2 = ((char*) str))
{
char* chPtr = str2;
do
{
if (chunkPrevious.m_ChunkLength > 0)
{
char[] chunkChars = chunkPrevious.m_ChunkChars;
int chunkOffset = chunkPrevious.m_ChunkOffset;
int chunkLength = chunkPrevious.m_ChunkLength;
if ((((ulong) (chunkLength + chunkOffset)) > str.Length) || (chunkLength > chunkChars.Length))
{
throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
fixed (char* chRef = chunkChars)
{
string.wstrcpy(chPtr + chunkOffset, chRef, chunkLength);
}
}
chunkPrevious = chunkPrevious.m_ChunkPrevious;
}
while (chunkPrevious != null);
}
return str;
}
Now, as I mentioned before I distinctly remember reading that this was the case in the early days if .NET. I even found a mention of in this book.
My question is, was this behavior dropped? If so, anyone knows why? It made perfect sense to me...