我今天遇到了这种情况。我有一个我正在测试平等的对象; Create()方法返回MyObject的子类实现。
MyObject a = MyObject.Create();
MyObject b = MyObject.Create();
a == b; // is false
a.Equals(b); // is true
注意我还在子类实现中覆盖了Equals(),它执行了一个非常基本的检查,以查看传入的对象是否为null并且是子类的类型。如果满足这两个条件,则认为对象是相等的。
另一个有点奇怪的是我的单元测试套件做了一些类似于
的测试Assert.AreEqual(MyObject.Create(), MyObject.Create()); // Green bar
并观察到预期结果。因此,我猜NUnit使用了封面下的a.Equals(b),而不是我假设的== b。
旁注:我使用.NET和Java混合编程,所以我可能会在这里混淆我的期望/假设。但是,我认为a == b在.NET中的工作比在Java中更一致,在Java中你经常需要使用equals()来测试相等性。
UPDATE 以下是Equals()的实现,如下所示:
public override bool Equals(object obj) {
return obj != null && obj is MyObjectSubclass;
}
答案 0 :(得分:32)
==
和Equals
之间的主要区别在于 ==
(与所有运算符一样)不是多态的,而Equals
(就像任何运算符一样)虚函数)。
默认情况下,引用类型会为==
和Equals
获得相同的结果,因为它们都会比较引用。当然也可以完全不同地编写运算符逻辑和Equals
逻辑,尽管这似乎是荒谬的。使用==
(或任何)运算符的最大问题来自于声明所需逻辑的更高级别(换句话说,将对象引用为未明确定义运算符或定义的父类它与真正的类不同)。在这种情况下,它引用的类的逻辑用于运算符,但Equals
的逻辑来自对象实际上 的任何类。 / p>
我想强调指出,仅基于您问题中的信息,绝对没有理由认为或假设Equals
将值与参考值进行比较。创建这样一个类非常容易,但这不是 语言规范。
提问后编辑
对于任何类的非空实例,Equals
的实现将返回true。虽然语法让我觉得你不是,但你可能会混淆is
C#关键字(确认类型)与VB.NET中的is
关键字(确认引用相等)。如果确实如此,那么您可以使用Object.ReferenceEquals(this, obj)
在C#中进行显式引用比较。
无论如何,这就是为什么你看到true
Equals
的原因,因为你传递了一个类的非空实例。
顺便提一下,您使用Equals
对NUnit的评论是出于同样的原因;因为运算符不是多态的,所以如果Assert
函数使用==
,则特定类无法定义自定义相等行为。
答案 1 :(得分:6)
答案 2 :(得分:3)
你自己几乎回答了你的问题:
我还在子类实现中覆盖了Equals(),它执行了一个非常基本的检查,以查看传入的对象是否为null并且是子类的类型。如果满足这两个条件,则认为对象是相等的。
==
运算符未被重载 - 所以它返回false
,因为a
和b
是不同的对象。但是a.Equals
正在调用您的覆盖,这可能会返回true
,因为a
和b
都不为空,并且它们都是子类的类型。
所以你的问题是“什么时候a == b可能是假的,而a.Equals(b)是真的吗?”在这种情况下你的答案是:当你明确地编码它时!
答案 3 :(得分:1)
在Java中,a == b检查两个对象的引用是否相等(如果这两个对象是同一个对象“别名”,则为rougly)
a.equals(b)比较两个对象所代表的值。
答案 4 :(得分:1)
除非在对象中专门重载以执行其他操作,否则它们都会执行相同的操作。
来自其他地方提到的Jon Skeet Article的引用。
Equals方法只是一个虚拟方法 一个在System.Object中定义的,和 被任何一个班级选择覆盖 这样做。 ==运算符是一个 可以超载的运算符 课程,但通常有 身份行为。
此处的关键字为 USUALLY 。可以编写它们来做基础课所要求的任何事情,而且他们也不必做同样的事情。
答案 5 :(得分:0)
我相信a == b会检查引用的对象是否相同。
通常要查看值是否相同a.Equals(b)被使用(为了工作,通常需要重写它。)
答案 6 :(得分:0)
“==”操作测试绝对相等(除非超载);也就是说,它测试两个对象是否是相同的对象。只有你将一个分配给另一个,即
,这才是真的MyObject a = MyObject.Create();
MyObject b = a;
仅仅设置两个对象的所有属性并不意味着对象本身。在引擎盖下,“==”运算符所比较的是内存中对象的地址。这样做的实际效果是,如果两个对象真正相等,那么改变其中一个对象的属性也会改变另一个对象,而如果它们只相似(“等于”相等),则不会。一旦你理解了这个原则,这就完全一致了。