StringBuilder and capacity?

I created a test application for testing, StringBuilder copies the data to another instance and generates its buffer when its length is greater than the current capacity and is checked in the ildasm.exe file, but it seems identical.

How to check that StringBuilder will copy its data to a new instance and increase the buffer at the specified limit?

+2
stringbuilder c #
source share
6 answers

If you want to test how StringBuilder works, just run Reflector and look at it. The implementation for StringBuilder.Append(string) as follows

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

See the section with NeedsAllocation , GetNewString , etc. to find what you are looking for.

+5
source share

Capacity is contiguous memory allocated for StringBuilder. Capacity can be> = string length. When more data than volume is added to StringBuilder, StringBuilder automatically increases capacity. Since the bandwidth is exceeded (that is, the continuous memory is full and there is no more buffer room), a large area of ​​the buffer is allocated and data is copied from the original memory to this new area.

It does not copy data to a new "instance", but to a new "memory location". The instance remains the same, but indicates a new memory location.

Change FYI: the default capacity for StringBuilder, if not specified at creation, is 16

If you want to see memory locations for StringBuilder, you can debug your applications and check memory using Debug> Windows> Memory. In fact, you can see the address of each byte stored in your StringBuilder when append stmt starts.

If you need to get seats with software this link may help.

+11
source share

Not that we really tested that StringBuilder works, because it is, but for your own pleasure you can always write unit test.

 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. 

Not surprisingly, it passes, and the following conclusion is provided.

     Capacity = 10 Length = 0 MaxCapacity = 2147483647
     Capacity = 40 Length = 30 MaxCapacity = 2147483647
+5
source share

The way StringBuilder expands its buffer when necessary is what StringBuilder's internal code takes care of; It will not be displayed in the IL code of your application; the compiler cannot know how large strings StringBuilder in a particular method will contain, since this can change from time to time.

However, when StringBuilder does indeed increase its buffer, this will not lead to the creation of a new instance of StringBuilder. This can cause it to copy the internal representation of the string it contains into a new instance (I don’t know the internal work of this class is enough to tell exactly what is going on).

+2
source share

You can use Reflector to see how StringBuilder works.

See method

 StringBuilder Append(string value) 

For .Net 3.5 logic, this is: if the buffer length is not enough for a new line, create a new buffer with a length equal to Max (oldSize * 2, requiredSize).

In other words, StringBuffer is trying to double the buffer, and if that is not enough, then the buffer size will be enough to fit the new line.

The link to the old buffer is deleted, and the old buffer is returned with the next garbage collection.

0
source share
  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 } } 
0
source share

All Articles