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

字符串驻留与内存地址疑问:IsInterned为true但引用不等?

问题解析:字符串驻留与ReferenceEquals的矛盾

先看你贴出的代码:

var a = "ab";
var b = string.Concat("a", "b");

Console.WriteLine(string.IsInterned(a)!=null); //True
Console.WriteLine(string.IsInterned(b)!=null); //True

Console.WriteLine(object.ReferenceEquals(a,b)); //False

这里的核心误解是对string.IsInterned方法的作用理解偏差:

  • string.IsInterned的逻辑是:如果传入的字符串内容在驻留表中存在,返回驻留表中的那个字符串引用;如果不存在,返回null。它并不会把传入的字符串本身加入驻留表(除非手动调用string.Intern)。
  • 变量a是编译期生成的字符串,编译器会自动将其加入字符串驻留表,所以a的引用就是驻留表中的"ab"对象。
  • 变量b是通过string.Concat在运行时生成的新字符串对象,这个对象并没有被自动加入驻留表。当你调用string.IsInterned(b)时,因为驻留表中已经有a对应的"ab",所以方法返回的是驻留表中的那个引用(也就是a的引用),因此判断IsInterned(b)!=null会得到true——但这并不代表b本身被驻留了,只是存在相同内容的驻留字符串而已。
  • 既然b是运行时新创建的独立对象,a是驻留表中的对象,二者引用自然不同,所以object.ReferenceEquals(a,b)返回false。

如果要让b和a引用相同,需要手动调用string.Intern将b的内容关联到驻留表:

var b = string.Intern(string.Concat("a", "b"));

此时object.ReferenceEquals(a,b)就会返回true,因为string.Intern会直接返回驻留表中已有的"ab"引用(如果存在的话)。

另外补充:编译期的字符串拼接(比如var c = "a"+"b")会被编译器直接优化成"ab",所以c会自动指向驻留表中的对象,和a引用相同,这也是你一开始误以为string.Concat会有同样行为的原因,但string.Concat是运行时执行的方法,编译器无法提前优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:52:41