何时a == b可以为假而a.Equals(b)为真?

ala*_*irs 25 .net c# .net-3.5

我今天遇到了这种情况.我有一个我正在测试平等的对象; Create()方法返回MyObject的子类实现.

MyObject a = MyObject.Create();
MyObject b = MyObject.Create();

a == b; // is false
a.Equals(b); // is true
Run Code Online (Sandbox Code Playgroud)

注意我还在子类实现中覆盖了Equals(),它执行了一个非常基本的检查,以查看传入的对象是否为null并且是子类的类型.如果满足这两个条件,则认为对象是相等的.

另一个有点奇怪的是我的单元测试套件做了一些类似的测试

Assert.AreEqual(MyObject.Create(), MyObject.Create()); // Green bar
Run Code Online (Sandbox Code Playgroud)

并观察到预期的结果.因此,我猜NUnit使用了封面下的a.Equals(b),而不是我假设的== b.

旁注:我使用.NET和Java混合编程,所以我可能会在这里混淆我的期望/假设.但是,我认为a == b在.NET中的工作比在Java中更一致,在Java中你经常需要使用equals()来测试相等性.

更新 以下是Equals()的实现,如下所示:

public override bool Equals(object obj) {
    return obj != null && obj is MyObjectSubclass;
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*son 32

==和之间的关键区别Equals==(像所有运算符一样)不是多态的,而Equals(就像任何虚函数一样).

默认情况下,引用类型将得到相同的结果==Equals,因为它们都比较引用.当然,Equals完全不同地编写运算符逻辑和逻辑代码也是可能的,尽管这似乎是荒谬的.最大的问题来自==于在声明所需逻辑的更高级别使用(或任何)运算符(换句话说,将对象引用为未明确定义运算符或以不同于true定义运算符的父类.类).在这种情况下,它的该类的逻辑引用作为用于运营商,但对于逻辑Equals来自任何类的对象实际上.

我想强调指出,完全基于你问题中的信息,绝对没有理由去思考或假设Equals比较价值与参考.创建这样一个类非常容易,但这不是语言规范.

后问题编辑编辑

Equals对于类的任何非null实例,您的实现将返回true .虽然语法让我觉得你不是,但你可能会混淆isC#关键字(确认类型)与isVB.NET中的关键字(它确认了引用相等).如果确实如此,那么您可以使用C#在C#中进行显式引用比较Object.ReferenceEquals(this, obj).

无论如何,这就是你所看到true的原因Equals,因为你传递了一个类的非null实例.

顺便提一句,您对NUnit使用的评论Equals是出于同样的原因; 因为运算符不是多态的,所以如果使用Assert函数,则特定类无法定义自定义相等行为==.

  • 这可能是我曾经问过的任何问题的最佳答案.感谢亚当,我希望我能为你提供的不仅仅是一次! (4认同)

Arv*_*rve 6

a == b检查它们是否引用同一个对象.

a.Equals(b)比较内容.

这是2004年Jon Skeet文章的链接,可以更好地解释它.

  • 我对这个答案收到的赞成水平感到困惑.这不仅完全不正确,而且乔恩的文章也不以任何方式支持这一立场. (7认同)
  • -1.绝对没有理由假设这里的"等于"基于对对象数据的深度检查来确定相等性. (4认同)
  • @Michael:字符串不正确.字符串覆盖`operator ==`,所以`a == b`也比较内容. (3认同)
  • 从那篇文章:"Equals方法只是在System.Object中定义的虚拟方法,并被任何类选择这样做所覆盖.==运算符是一个可以由类重载但通常具有标识行为的运算符. " 这个重要的词是USUALLY. (2认同)