Я отчетливо помню с первых дней существования .NET, что вызов ToString в StringBuilder использовался для предоставления нового строкового объекта (который должен быть возвращен) с внутренним буфером символов, используемым StringBuilder. Таким образом, если вы создали огромную строку с помощью StringBuilder, вызов ToString не должен был ее копировать.
При этом StringBuilder должен был предотвратить любые дополнительные изменения в буфере, потому что теперь он использовался неизменной строкой. В результате StringBuilder переключился бы на «копирование при изменении», при котором любая попытка изменения сначала создаст новый буфер, скопирует в него содержимое старого буфера и только затем изменит его.
Я думаю, это предположение заключался в том, что StringBuilder будет использоваться для создания строки, затем преобразован в обычную строку и отброшен. Мне кажется, что это разумное предположение.
Вот в чем дело. Я не могу найти упоминания об этом в документации. Но я не уверен, что это когда-либо было задокументировано.
Итак, я посмотрел на реализацию ToString с использованием Reflector (.NET 4.0), и мне кажется, что он действительно копирует строку, а не просто разделяет буфер:
[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;
}
Теперь, как я уже упоминал ранее, я отчетливо помню, как читал, что это имело место в первые дни существования .NET. Я даже нашел упоминание в этой книге .
Мой вопрос: было ли это поведение отброшено? Если да, то кто-нибудь знает почему? Для меня это имело смысл ...