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

本文关键字:情况 输出 比较 为什么 我们 字符串 | 更新日期: 2023-09-27 17:56:47

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

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 !?

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

答案很简单:

objectstring进行比较时,将使用引用比较,仅当两个对象具有相同的引用时,才会为真。

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

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

增加的复杂性是前两个字符串具有相同的引用,因为它们是编译时常量,并且已由编译器interned,以便它们引用内存中的同一字符串。

我用这个解释注释了你的原始代码:

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 获得相同的结果,如下所示:

    字符串 str2 = 字符串。Concat("Int", "32");

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行现在是 false,因为它也在比较这些字符串的引用。

相关文章: