Вопрос

Я создал тестовое приложение для тестирования, Is StringBuilder копирует данные в другой экземпляр и увеличивает его буфер, когда его длина превышает текущую емкость, и проверяет в ildasm.exe но это кажется идентичным.

Как проверить, что StringBuilder скопирует свои данные в новый экземпляр и увеличит буфер на указанный предел?

Это было полезно?

Решение

Если вы хотите проверить, как реализован StringBuilder, просто запустите Reflector и посмотрите на него.Реализация для StringBuilder.Append(string) заключается в следующем

public StringBuilder Append(string value)
{
   if (value != null)
   {
      string stringValue = this.m_StringValue;
      IntPtr currentThread = Thread.InternalGetCurrentThread();
      if (this.m_currentThread != currentThread)
      {
         stringValue = string.GetStringForStringBuilder(stringValue, stringValue.Capacity);
      }
      int length = stringValue.Length;
      int requiredLength = length + value.Length;
      if (this.NeedsAllocation(stringValue, requiredLength))
      {
         string newString = this.GetNewString(stringValue, requiredLength);
         newString.AppendInPlace(value, length);
         this.ReplaceString(currentThread, newString);
      }
      else
      {
         stringValue.AppendInPlace(value, length);
         this.ReplaceString(currentThread, stringValue);
      }
   }
   return this;
}

Посмотрите на раздел с NeedsAllocation, GetNewString и так далее, чтобы найти то, что вы ищете.

Другие советы

Емкость представляет непрерывную память, выделенную StringBuilder.Емкость может быть >= длиной строки.Когда в StringBuilder добавляется больше данных, чем требуется, StringBuilder автоматически увеличивает емкость.Поскольку емкость превышена (то есть непрерывная память заполнена и больше не доступно буферное пространство), выделяется большая буферная область, и данные копируются из исходной памяти в эту новую область.

Он копирует данные не в новый "экземпляр", а в новую "ячейку памяти".Экземпляр остается тем же, но указывает на новую ячейку памяти.

Редактировать К ТВОЕМУ СВЕДЕНИЮ:Емкость StringBuilder по умолчанию, если она не указана при создании, равна 16

Если вы хотите увидеть ячейки памяти для StringBuilder, вы можете отладить свои приложения и проверить память, используя Debug > Windows > Memory.На самом деле вы можете видеть адрес каждого байта, хранящегося в вашем StringBuilder, когда выполняется Append stmt.

Если вам нужно получить местоположения программно эта ссылка могло бы помочь.

Не то чтобы мы действительно тестировали, работает ли StringBuilder, потому что это так, но для вашего собственного удовольствия вы всегда можете написать модульный тест.

StringBuilder sb = new StringBuilder(10);
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
sb.Append("1234567890");
sb.Append("1234567890");
sb.Append("1234567890");
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
Assert.AreEqual("123456789012345678901234567890"
      , sb.ToString()); // NUnit assert.

Неудивительно, что это проходит, и выдается следующий результат.

    Capacity = 10 Length = 0 MaxCapacity = 2147483647
    Capacity = 40 Length = 30 MaxCapacity = 2147483647

Способ, которым StringBuilder увеличивает свой буфер, когда это необходимо, - это то, о чем заботится внутренний код StringBuilder;это не будет отображаться в IL-коде вашего приложения;компилятор не может знать, какого размера строки будет содержать StringBuilder в определенном методе, поскольку это может меняться время от времени.

Однако, когда StringBuilder делает увеличьте его буфер, это не приведет к созданию нового экземпляра StringBuilder.Это может привести к тому, что он скопирует внутреннее представление строки, которую он содержит, в новый экземпляр (я недостаточно знаю о внутренней работе класса, чтобы точно сказать, что происходит).

Вы можете использовать Reflector, чтобы в значительной степени увидеть, как работает StringBuilder.

Смотрите метод

StringBuilder Append(string value)

Для .Net 3.5 логика заключается в следующем:если длины буфера недостаточно для новой строки, создайте новый буфер длиной, равной Max(OldSize * 2, requiredSize).

Другими словами, StringBuffer пытается удвоить буфер, и если этого недостаточно, то увеличивает размер буфера ровно настолько, чтобы вместить новую строку.

Ссылка на старый буфер удаляется, а старый буфер восстанавливается при следующей сборке мусора.

 class Program
    {
        static void Main()
        {
            StringBuilder sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16

            for (int i = 0; i < 50; i++) 
                sb.Append(i + ",");

            Console.WriteLine(sb.Capacity); //256

            sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top