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

为何C#中使用StringBuilder时内存地址仍存在差异?

为什么StringBuilder操作后内存地址看起来不一样?

你犯了一个关键的测试错误:你没有检测StringBuilder内部缓冲区的内存地址,而是检测了每次调用ToString()生成的全新字符串的地址,这自然会导致两次地址不同。

问题根源拆解

  1. StringBuilder.ToString()会创建新字符串
    每次调用ToString(),都会将StringBuilder内部缓冲区的内容复制到一个全新的string实例中。由于C#的字符串是不可变的,这个新字符串会被分配到新的内存区域,所以每次的地址必然不同。你看到的地址是这些临时字符串的地址,而非StringBuilder内部存储字符的缓冲区地址。

  2. StringBuilder的可变性针对内部缓冲区
    StringBuilder的高效性来自它内部维护的可变字符数组缓冲区:

    • 当调用Append()时,如果现有缓冲区有足够空间,会直接在原有缓冲区追加内容,此时内部缓冲区的地址保持不变;
    • 如果追加内容超过缓冲区容量,StringBuilder会重新分配一块更大的缓冲区(此时内部缓冲区地址会变化),但这个变化你并没有检测到。

修正测试:检测StringBuilder内部缓冲区地址

如果你想验证StringBuilder内部缓冲区的地址变化,可以通过反射获取其内部缓冲区(注意:不同.NET版本的内部字段名可能略有差异,以下基于.NET Framework/.NET Core常见实现):

using System.Reflection;

// ... 原有代码 ...

Console.WriteLine("Using String Builder to (mutable string)");
StringBuilder str2 = new StringBuilder();

str2.Append("Interview");
Console.WriteLine("str2 text is:" + str2);
// 获取内部缓冲区地址
var chunkCharsField = typeof(StringBuilder).GetField("_chunkChars", BindingFlags.NonPublic | BindingFlags.Instance);
char[] internalBuffer = (char[])chunkCharsField.GetValue(str2);
unsafe
{
    fixed (char* pointer = internalBuffer)
    {
        Console.WriteLine("StringBuilder内部缓冲区地址: " + (int)pointer);
    }
}

str2.Append("Selection Process");
Console.WriteLine("str2 modified text is: " + str2);
// 再次获取内部缓冲区地址
internalBuffer = (char[])chunkCharsField.GetValue(str2);
unsafe
{
    fixed (char* pointer = internalBuffer)
    {
        Console.WriteLine("StringBuilder修改后内部缓冲区地址: " + (int)pointer);
    }
}

如果初始缓冲区容量足够容纳追加的内容,两次输出的内部缓冲区地址会相同;如果容量不足触发了扩容,地址才会变化。

总结

你的测试代码误将ToString()生成的新字符串地址当作StringBuilder的内存地址,这才导致结果与预期不符。StringBuilder的可变性体现在内部缓冲区的复用/扩容上,而非每次生成的字符串对象地址不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:42:53