System.Text.StringBuilder Constraint

I read that the StringBuilder type has a limitation (16 characters by default), and when you add some text to it, a new instance with a higher limit is created outside it, and the data is copied to This. I tried using the following code:

StringBuilder test = new StringBuilder("ABCDEFGHIJKLMNOP",16);
test.Append("ABC");

And the CIL generated for this was:

  .maxstack  3
  .locals init (class [mscorlib]System.Text.StringBuilder V_0)
  IL_0000:  nop
  IL_0001:  ldstr      "ABCDEFGHIJKLMNOP"
  IL_0006:  ldc.i4.s   16
  IL_0008:  newobj     instance void [mscorlib]System.Text.StringBuilder::.ctor(string, int32)
  IL_000d:  stloc.0
  IL_000e:  ldloc.0
  IL_000f:  ldstr      "ABC"
  IL_0014:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0019:  pop
  IL_001a:  ret

Setting a limit, say 32:

StringBuilder test = new StringBuilder("ABCDEFGHIJKLMNOP",32);
test.Append("ABC");

Created exactly the same IL code. What I expect is to create a new instance in the first case and change the value of the instance in the second case, which obviously did not happen, tell me why?

+3
source share
4 answers

Everything funny happens on this line:

IL_0014:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)

Append(), IL . StringBuilder ( , ), , Append().

. Append(), , , .

+8

#

using System.Text;

internal class Program
{
    internal static void Main(string[] args)
    {
        StringBuilder test = new StringBuilder("ABCDEFGHIJKLMNOP", 16);
        test.Append("ABC");

        StringBuilder test2 = new StringBuilder("ABCDEFGHIJKLMNOP", 32);
        test2.Append("ABC");
    }
}

IL ( Reflector):

.class private auto ansi beforefieldinit Program
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: call instance void [mscorlib]System.Object::.ctor()
        L_0006: ret 
    }

    .method assembly hidebysig static void Main(string[] args) cil managed
    {
        .entrypoint
        .maxstack 3
        .locals init (
            [0] class [mscorlib]System.Text.StringBuilder test,
            [1] class [mscorlib]System.Text.StringBuilder test2)
        L_0000: nop 
        L_0001: ldstr "ABCDEFGHIJKLMNOP"
        L_0006: ldc.i4.s 0x10
        L_0008: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(string, int32)
        L_000d: stloc.0 
        L_000e: ldloc.0 
        L_000f: ldstr "ABC"
        L_0014: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
        L_0019: pop 
        L_001a: ldstr "ABCDEFGHIJKLMNOP"
        L_001f: ldc.i4.s 0x20
        L_0021: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(string, int32)
        L_0026: stloc.1 
        L_0027: ldloc.1 
        L_0028: ldstr "ABC"
        L_002d: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
        L_0032: pop 
        L_0033: ret 
    }
}

, 0x10 0x20 test test2, , , , IL ?

+3

StringBuilder Capacity, Collection. , ( ) , , ( StringBuilder List < > ) . , .

- , endresult, - :

var sb = new StringBuilder(n); // set initial Capacity=n

, , . , .

, (StringBuilder char), . , , , .

+2
source

I think you are reading IL code incorrectly. Next line:

 IL_0014:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)

... does not mean that a new instance of StringBuilder is being created; it is just a method call Append.

If the call Appendcauses the string to be longer than the current capacity StringBuilder, it will create a new instance Stringinside; it will still be the same instance StringBuilder.

+1
source

Source: https://habr.com/ru/post/1711737/


All Articles