You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StringBuilder扩容是否创建新实例?与书籍描述的冲突疑问

关于StringBuilder扩容是否创建新实例的疑问

我写了一段测试代码,查看其IL代码后发现只有一行newobj指令,也就是只创建了一个StringBuilder实例。但《Pro C#10 with .Net 6》第89页提到:

If you append more characters than the specified limit, the StringBuilder object will copy its data into a new instance and grow the buffer by the specified limit.
(中文译:当添加的字符超过指定限制时,StringBuilder对象会将其数据复制到新实例中,并按指定限制扩容缓冲区)

这让我产生疑问:我的理解是不是有错误?

测试代码

StringBuilder sb = new StringBuilder("test", 4);
sb.Append('\n');
sb.AppendLine("test1");
sb.AppendLine("test2");
sb.AppendLine("test3");
sb.AppendLine("test4");

对应的IL代码

// [3 1 - 3 49]
    IL_0000: ldstr        "test"
    IL_0005: ldc.i4.4
    IL_0006: newobj       instance void [System.Runtime]System.Text.StringBuilder::.ctor(string, int32)
    IL_000b: stloc.0      // sb

    // [4 1 - 4 17]
    IL_000c: ldloc.0      // sb
    IL_000d: ldc.i4.s     10 // 0x0a
    IL_000f: callvirt     instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::Append(char)
    IL_0014: pop

    // [5 1 - 5 24]
    IL_0015: ldloc.0      // sb
    IL_0016: ldstr        "test1"
    IL_001b: callvirt     instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::AppendLine(string)
    IL_0020: pop

    // [6 1 - 6 24]
    IL_0021: ldloc.0      // sb
    IL_0022: ldstr        "test2"
    IL_0027: callvirt     instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::AppendLine(string)
    IL_002c: pop

    // [7 1 - 7 24]
    IL_002d: ldloc.0      // sb
    IL_002e: ldstr        "test3"
    IL_0033: callvirt     instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::AppendLine(string)
    IL_0038: pop

    // [8 1 - 8 24]
    IL_0039: ldloc.0      // sb
    IL_003a: ldstr        "test4"
    IL_003f: callvirt     instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::AppendLine(string)
    IL_0044: pop
    IL_0045: ret

解答

你没有理解错,但书中的描述存在用词不准确的问题——StringBuilder扩容时并不会创建新的实例对象,而是会重新分配内部的字符缓冲区数组,把原有数据复制到新的缓冲区里,实例本身还是同一个。

你看到的IL代码里只有一个newobj指令,完全符合实际运行逻辑:

  • 你创建的StringBuilder初始容量是4,初始字符串"test"刚好占满4个字符。
  • 后续的Append和AppendLine操作会触发扩容,但扩容仅针对内部的char数组,不会创建新的StringBuilder对象,所以IL里不会出现新的newobj指令。

书中的描述可能是把“新的缓冲区数组”误表述成了“新实例”。实际查看.NET源码就能确认:StringBuilder的扩容逻辑是重新分配更大的内部数组,复制数据后替换原有数组,整个过程中实例引用始终不变。

内容的提问来源于stack exchange,提问作者Humble Newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:07:15