繁体   English   中英

在 CLR 中如何创建和管理字符串?

[英]How strings are created and managed in CLR?

我和我的朋友正在讨论 Do.net 框架中的字符串,它们如何是引用类型但表现得像值类型(不可变)。 我们都知道字符串是 CLR 内部的,但我们并没有真正在简短的讨论中得出结论,字符串是如何由 CLR/Framework 创建和管理的。

例如,在下面的代码中,显然s1s2是不同的实例,但是正如您看到的,当我s2.ToUpper()时,结果返回到s1

    public static void Main (string[] args)
    {
        string s1 = "HELLO";
        string s2 = "hello";

        Console.WriteLine (s1.GetHashCode()); //Prints 68624562
        Console.WriteLine (s2.GetHashCode()); //Prints 99162322
        Console.WriteLine (s2.ToUpper().GetHashCode()); //Prints 68624562 too!
    }

因此,问题在于调用s2.ToUpper()时 CLR 是否创建了新字符串"HELLO"并检查它是否已经存在,如果是则丢弃新创建的字符串? 有人可以解释这里的魔法吗?

String.GetHashCode() 生成一个基于字符串内容的 hash 值。 因此,相同的字符串生成相同的 hash 是完全自然的。这意味着您无法断定 ToUpper() 返回的字符串引用必须与 s1 引用匹配。 事实并非如此,实施起来太昂贵了。

您可以通过测试此代码来验证:

    static void Main(string[] args) {
        var s1 = "hello";
        var s2 = "HELLO";
        var s3 = s1.ToUpper();
        bool eq = object.ReferenceEquals(s2, s3);
        System.Diagnostics.Debug.Assert(!eq);
    } 

对于相同的输入,两次GetHashCode()调用给出相同的结果也就不足为奇了,这就是散列的意义所在……

相反,当你这样做时:

Console.WriteLine(Object.ReferenceEquals(s2.ToUpper(), s1));

它只是返回false 因此,您实际上有两个string实例,它们都具有相同的内容。

我认为您需要复习有关散列、散列码和相等性的知识。

或者您来自 Java? 也许您的印象是 hash 代码与 object 参考值相关,因为Object.getHashCode()的文档指出:

在相当实用的情况下,class Object 定义的 hashCode 方法确实会为不同的对象返回不同的整数。 (这通常是通过将 object 的内部地址转换为 integer 来实现的,但是 JavaTM 编程语言不需要这种实现技术。)

您不能使用GetHashCode()来唯一标识实例。 对于具有相同值的两个不同对象,hash 代码必须相同。 否则它不会作为 hash 代码工作。

s2.ToUpper() 只是方法调用,不会更改 s2 object 的值(s2 是 String 类型的 object)。 它采用 s2 的值并返回具有“HELLO”值(ToUpper() 方法的结果)的 String class 的新实例。 在Main function的scope中还有两个对象s1和s2,它们的值保持不变。

要添加,请回答您的另一部分...

如果您还检查此Object.ReferenceEquals(s2.ToUpper(), s2)您会发现它也是错误的。

字符串是immutable的——这意味着在这种情况下ToUpper()返回一个新实例。

所以答案是肯定的,“HELLO”是新字符串。

但是,正如其他人所说, GetHashCode()只是一个“哈希值”——它主要用于在处理哈希和字典时使用不同的算法来“填充桶”。

或者查看此链接什么是覆盖 System.Object.GetHashCode 的最佳算法? - 和答案 - 让您很好地了解 hash 算法的工作原理 - 为什么它不是唯一的 - 以及为什么对于具有相同内容的字符串它可能相同。

或者这个http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM