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