Pergunta

Eu criei o aplicativo de teste para testar, é o StringBuilder copiar dados para outra instância e cultivar o buffer de TI quando seu comprimento é mais do que a capacidade atual e verifique no ildasm.exe, mas parece idêntico.

Como verificar o StringBuilder copiará seus dados em nova instância e aumentará o buffer pelo limite especificado?

Foi útil?

Solução

Se você deseja inspecionar como o StringBuilder é implementado, basta iniciar o refletor e olhar para ele. A implementação para StringBuilder.Append(string) é o seguinte

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;
}

Veja a seção com NeedsAllocation, GetNewString E assim por diante para encontrar o que você está procurando.

Outras dicas

A capacidade representa a memória contígua alocada para o StringBuilder. A capacidade pode ser> = comprimento da string. Quando mais dados são anexados ao StringBuilder que a capacidade, o StringBuilder aumenta automaticamente a capacidade. Como a capacidade excedeu (ou seja, a memória contígua é preenchida e não há mais sala buffer disponível), uma área de buffer maior é alocada e os dados são copiados da memória original para esta nova área.

Ele não copia dados para a nova 'instância', mas para o novo 'local da memória'. A instância permanece a mesma, mas aponta para o novo local da memória.

Editar FYI: Capacidade padrão do StringBuilder se não for especificado durante a criação é 16

Se você quiser ver os locais de memória do StringBuilder, poderá depurar seus aplicativos e verificar a memória usando a depuração> Windows> Memory. Na verdade, você pode ver o endereço de todos os bytes armazenados no seu StringBuilder quando o Apend STMT é executado.

Se você precisar obter os locais programaticamente esse link pode ajudar.

Não que estejamos realmente testando que o StringBuilder funcione, porque faz, mas, para sua própria diversão, você sempre pode escrever um teste de unidade.

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.

Sem surpresa, passa e a seguinte saída é fornecida.

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

A maneira como o StringBuilder aumenta seu buffer quando necessário é algo que é atendido pelo código interno do StringBuilder; Não será exibido no código IL do seu aplicativo; O compilador não pode saber quão grandes o StringBuilder em um determinado método conterá, pois isso pode variar de tempos em tempos.

No entanto, quando o Stringbuilder faz Aumente seu buffer, ele não resultará em uma nova instância do StringBuilder. Isso pode resultar na cópia da representação interna da string que ela mantém em uma nova instância (não sei o suficiente do funcionamento interno da classe para dizer exatamente o que acontece).

Você pode usar o refletor para ver praticamente como o StringBuilder funciona.

Veja o método

StringBuilder Append(string value)

Para .NET 3.5 Lógica é a seguinte: Se o comprimento do buffer não for suficiente para a nova string, crie um novo buffer com comprimento igual ao max (OldSize * 2, requerirsize).

Em outras palavras, o StringBuffer tenta dobrar o buffer e, se isso não for suficiente, produza o tamanho do buffer apenas o suficiente para caber na nova string.

A referência ao buffer antigo é removida e o buffer antigo é recuperado com a próxima coleção de lixo.

 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
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top