我今天遇到了这种情况。我有一个正在测试是否相等的对象; 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),而不是我假设的 a == 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
将值与引用进行比较。创建这样一个类非常容易,但这不是语言规范。
问后编辑编辑
Equals
的实现将为您类的任何非空实例 返回 true。虽然语法让我认为你不是,但你可能会混淆 is
C# 关键字(确认类型)与 VB.NET 中的 is
关键字(确认类型)引用平等)。如果情况确实如此,那么您可以在 C# 中使用 Object.ReferenceEquals(this, obj)
进行显式引用比较。
无论如何,这就是您看到 Equals
为 true
的原因,因为您传递的是类的非空实例。
顺便说一句,出于同样的原因,您对使用 Equals
的 NUnit 的评论也是正确的;因为运算符不是多态的,所以如果 Assert
函数使用 ==
,则特定类将无法定义自定义相等行为。
关于c# - 什么时候 a == b 可以为假而 a.Equals(b) 为真?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2494156/