【问题标题】:How does == work and what does it do internally .NET== 如何工作以及它在 .NET 内部做什么
【发布时间】:2014-10-02 17:54:35
【问题描述】:

这是我的示例代码。

string a = "test";

object c = a;

Console.WriteLine(a == c);

Console.WriteLine(object.Equals(a, c));

Console.WriteLine(a.Equals(c));

Console.WriteLine(c.Equals(a));

本例输出如下

True
True
True
True

这是另一个代码示例

string a = "test";

string b = "te";

object c = b + "st";

Console.WriteLine(a == c);

Console.WriteLine(object.Equals(a, c));

Console.WriteLine(a.Equals(c));

Console.WriteLine(c.Equals(a));

现在这个例子更有趣了,因为输出是这样的

False
True
True
True

这真的让我感动,让我问自己一个问题,== 如何比较两个对象?我寻找答案,但找不到任何可以解释的东西?谁能解释一下。这是在使用 .NET 4.5.1 的机器上执行的

【问题讨论】:

  • 提示:==string 重载。因此,如果两个操作数都是string(操作数的编译时类型,而不是执行时类型),它将调用重载,检查字符串是否相等而不是引用相等。
  • 看看herehere。这几乎是内部的。
  • 扩展@JonSkeet 所说的内容:如果您将c 声明为string,或者将其转换为字符串(a == (string)c),那么比较将返回true。这是string(以及极少数其他类型)特有的行为,这是string 是不可变类(而不是值类型)的结果。
  • 好的,但是你怎么解释,在这两种情况下,对象 c 都指的是同一个“测试”文字字符串,在这两种情况下都是实习的,如果我的知识是正确的字符串 a 和对象 c 在这两种情况下案例应该引用文字字符串“test”
  • 查看我的答案,了解关于字符串实习和参考比较的推理。

标签: .net equality


【解决方案1】:

对于引用类型,默认情况下,== 是一个引用比较器。正如 Jon Skeet 在他的评论中指出的那样,string 覆盖了这种行为,因此它可以提供值匹配语义。也就是说,您尝试的方案将在两个变量的类型均为string 的情况下工作。 c 被键入为 object 的事实意味着 == 的重载没有被使用。

字符串是不同的引用,尽管您可能会想到实习,因为字符串实习仅在默认情况下发生在编译时。在运行时,字符串仅在您手动调用 string.Intern 时才被保留,而您的 c 仅在运行时已知(编译器无法对其进行优化)。因此,这个 sn-p 手动使用字符串实习并使代码按照您希望的方式运行:

string a = "test";
string b = "te";
object c = string.Intern(b + "st");
// c == a is true

(最后一行查找字符串的内部版本,并返回该实例而不是创建一个新实例。)

同样,如果编译器不能保证字符串的值(因为字符串是一个变量,而不是文字或常量),它不会被实习。这一次,我将稍微调整您的示例,以演示我们如何使 c 的值成为编译时常量:

string a = "test";     // a literal, "test" - always fixed at compile time
const string b = "te"; // a constant - always fixed at compile time
object c = b + "st";   // a constant plus a literal - always fixed at compile time
// c == a is true

值得注意的是,当您在原始代码中比较 a == c 时会出现编译器警告:“可能是意外的引用比较;要进行值比较,请将右侧转换为类型 'string'。”警告值得关注! ;-)

【讨论】:

    【解决方案2】:
    Console.WriteLine(object.Equals(a, c));
    
    Console.WriteLine(a.Equals(c));
    
    Console.WriteLine(c.Equals(a));
    

    工作方式相同,因为它们是在比较对象的值,而

    Console.WriteLine(a == c);
    

    比较 a 和 c 对该值的引用

    【讨论】:

      猜你喜欢
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 2023-03-06
      • 1970-01-01
      • 2020-08-06
      • 2011-12-16
      相关资源
      最近更新 更多