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

时间:2010-03-22 16:59:32

标签: c# .net .net-3.5

我今天遇到了这种情况。我有一个我正在测试平等的对象; 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;
}

7 个答案:

答案 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)

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

a.Equals(b)比较内容。

这是2004年Jon Skeet文章的link,可以更好地解释它。

答案 2 :(得分:3)

你自己几乎回答了你的问题:

  

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

==运算符未被重载 - 所以它返回false,因为ab是不同的对象。但是a.Equals正在调用您的覆盖,这可能会返回true,因为ab都不为空,并且它们都是子类的类型。

所以你的问题是“什么时候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;

仅仅设置两个对象的所有属性并不意味着对象本身。在引擎盖下,“==”运算符所比较的是内存中对象的地址。这样做的实际效果是,如果两个对象真正相等,那么改变其中一个对象的属性也会改变另一个对象,而如果它们只相似(“等于”相等),则不会。一旦你理解了这个原则,这就完全一致了。

相关问题