代码之家  ›  专栏  ›  技术社区  ›  123Developer

是因为CLR的字符串池还是GetHashCode()方法的字符串池?

  •  1
  • 123Developer  · 技术社区  · 17 年前

    string s1 = "xyz";
    string s2 = "xyz";
    Console.WriteLine(" s1 reference equals s2 : {0}", object.ReferenceEquals(s1, s2));
    

    我相信,这并不是因为GetHashCode()对两个字符串实例返回相同的值。因为,我使用自定义对象进行了测试,并重写了GetHasCode()方法,每次都返回一个常量。此对象的两个单独实例在引用中不相等。

    请告诉我,幕后发生了什么。

    谢谢

    5 回复  |  直到 17 年前
        1
  •  14
  •   Tom Ritter    17 年前

    听起来像 string interning -一种只存储字符串一个副本的方法。它要求字符串在您处理的语言中是不可变类型,并且。Net满足了这一点,并使用了字符串接口。

    在字符串内部,字符串“xyz”存储在内部池中,每当您在内部说“xyz“时,它都会引用池中的条目。这可以通过只存储一次字符串来节省空间。因此,对“xyz”==“xyz“的比较将被解释为[指向34576的指针]==[指向34576],这是真的。

        2
  •  6
  •   Jon Skeet    17 年前

    这肯定是由于字符串实习。哈希码是 从不 在与参考进行比较时计算 object.ReferenceEquals .

    根据C#规范,第2.4.4.5节:

    每个字符串文字都不 必然会产生一个新字符串 根据以下公式等价的文字 到字符串相等运算符 (§7.9.7)出现在同一程序中, 这些字符串文字引用 相同的字符串实例。

    注意这个字符串 常量表达式 在这种情况下计为文字,因此:

    string x = "a" + "b";
    string y = "ab";
    

    这是有保证的 x y 也引用相同的对象(即它们是相同的引用)。

    顺便说一句,当规范中说“程序”时,它实际上意味着“组装”。不同程序集中相等字符串的行为取决于以下因素 CompilationRelaxations.NoStringInterning 以及精确的CLR实现和执行时间情况(例如,程序集是否被初始化)。

        3
  •  4
  •   Guffa    17 年前

    程序集中的任何字符串文字只存在一次。编译器对所有出现的字符串文字“xyz”使用相同的常量字符串。由于字符串是不可变的(您永远无法更改字符串实例的值),编译器可以安全地将同一字符串实例用于单独的字符串引用。

    如果你在运行时创建一个字符串,你会得到一个单独的实例:

    string s1 = "xyz";
    
    string s2 = "xy";
    s2 += "z";
    
    Console.WriteLine("s1 ref = s2 : {0}", object.ReferenceEquals(s1, s2));
    

    输出:

    s1 ref = s2 : False
    
        4
  •  0
  •   Community Mohan Dere    9 年前

    完全同意 Tom's answer ...

    摘录自 CIL Specification (第126页) :

    CLI保证以下结果 两条ldstr指令涉及 具有相同的两个元数据令牌 字符序列,返回 完全相同的字符串对象(a 称为字符串内部处理的过程)。

        5
  •  0
  •   Shay Erlichmen    17 年前

    字符串实习与此无关。

    如果发现这一点,我会非常惊讶。NET/C#编译器隐式调用Intern,在运行时检查匹配字符串对CPU来说压力太大。