字符串比较:为什么我们在以下情况下有不同的输出

时间:2015-06-17 10:46:35

标签: c# string

为什么我们对以下情况有不同的输出:

object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?

2 个答案:

答案 0 :(得分:7)

答案很简单:

当您将objectstring进行比较时,会使用参考比较,只有两个对象具有相同的参考时才会生效。

比较字符串时,使用字符串比较,如果字符串内容相同,则无论它们是否是相同的引用,都将为true。

在你的第三次比较中,你正在使用object比较来比较两个具有相同内容但具有不同引用的字符串,因此它将返回false。

增加的复杂性是前两个字符串具有相同的引用,因为它们是编译时常量并且已经interned by the compiler,因此它们引用内存中的相同字符串。

我已使用以下解释注释了您的原始代码:

object obj = "Int32";            // As a compile-time constant string, this will be interned.
string str1 = "Int32";           // This is also interned, so has the same reference as obj
string str2 = typeof(int).Name;  // Same contents as str1, but a different reference 
                                 // (created at runtime, so it wasn't interned)
Console.WriteLine(obj == str1);  // Reference comparison: true because the references are the same
Console.WriteLine(str1 == str2); // String comparison: true because the string contents are the same.
Console.WriteLine(obj == str2);  // Reference comparison: false because the references different.

此外:

  • 如果您正在使用Resharper,它实际上会警告您进行第一次和最后一次比较,并说:"可能的非预期参考比较"。
  • 您可以通过声明str2获得相同的结果,如下所示:

    string str2 = string.Concat(" Int"," 32");

答案 1 :(得分:1)

obj == str2行使用参考比较。而obj == str1行没有。

为什么?

.NET中的string类型是隐式引用类型。但它不是在同一时间。它是技术上属于引用类型的那些类型之一,但它被编程为值类型,并且不可变,这意味着它没有直接修改。

当您创建新的string时,会为其分配一个引用,该引用就是您的string变量所持有的引用。你可以使用string做各种各样的事情,但你永远无法改变它。如果重新分配值,它只会创建一个新的引用。

在这种情况下,obj == str1行使用参考比较,但参考文件实际匹配。因为它们都是硬编码的,所以编译器和.NET可以为每个使用相同的引用。 (正如我们之前所说的,字符串是不可变的。)您应该阅读Matthew发布的interning链接以获取更多信息。

因此,如果字符串匹配,为什么.NET会创建不同的引用?

考虑您可以在内存中创建的重要数量的对象。如果您在任何时候创建了新的string并且.NET通过所有其他字符串找到匹配的字符串,那么您的程序将非常慢。你几乎不会完成任何真正的工作。

因此,.NET优化了这一点。如果你稍微更改一下代码,你会明白我的意思。

object obj = "Int32";
string str1 = typeof(int).Name;
string str2 = typeof(int).Name;
Console.WriteLine(obj == str1); // false
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?

str1 == str2行仍然返回true,因为它实际上是比较字符串,而obj == str1行现在是假的,因为它也在比较那些引用。