Search code examples
.netvb.net.net-4.7.2

When a StringBuilder enlarges to accommodate a larger string, can the size increase be controlled separately from the Capacity?


When a StringBuilder enlarges to accommodate a larger string, can the size of the increase be controlled separately from Capacity?

The code below demonstrates the issue. StringBuilder uses the initial Capacity for the increment, thus doubling in size for just one extra character.

But what if I need a large initial capacity, and small size increases? For instance, StringBuilder(16384) would double in size to 32768. But I only need small increases like 16 or 32.

Can the increment size be changed? Instead of using Capacity()?

I found the comment below in the documentation for Append(). Perhaps what I describe is what this refers to?

In .NET Core and in the .NET Framework 4.0 and later versions, when you instantiate the StringBuilder object by calling the StringBuilder(Int32, Int32) constructor, both the length and the capacity of the StringBuilder instance can grow beyond the value of its MaxCapacity property. This can occur particularly when you call the Append(String) and AppendFormat(String, Object) methods to append small strings.

Imports System.Text
Module Module1
    Public Sub main()
        Dim sb As StringBuilder = New StringBuilder(64)
        Dim str As String
        str = StrDup(64, "x")
        sb.Append(str) '64 charcters.
        Console.WriteLine("Results:")
        Console.WriteLine("{0,-68} Capacity={1}", sb.ToString, sb.Capacity.ToString)
        sb.Append("y") 'One more.
        Console.WriteLine("{0,-68} Capacity={1}", sb.ToString, sb.Capacity.ToString)
        Console.WriteLine("Press any key to close.")
        Console.ReadKey()
    End Sub
End Module

Results:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx     Capacity=64
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy    Capacity=128
Press any key to close.

Solution

  • According to the source code, setting Capacity manually directly changes the size of the StringBuilder backing field, it does not use the current Length as part of that.

    So you can just manually set it

    Dim sb As StringBuilder = New StringBuilder(64)
    sb.Append("x"c, 64) '64 charcters.
    Console.WriteLine("Results:")
    Console.WriteLine("{0,-68} Capacity={1}", sb.ToString, sb.Capacity.ToString)
    
    sb.Capacity += 1
    sb.Append("y") 'One more.
    Console.WriteLine("{0,-68} Capacity={1}", sb.ToString, sb.Capacity.ToString)
    

    dotnetfiddle