为什么Contains方法和==运算符对对象的比较结果不同?

14
Object t = 4;
Object s = 4;

if (t == s) {       // false
}

List<Object> q = new List<object>() { t };
Boolean found = q.Contains(s);          // found = true!

在上面的代码中,t == s 返回 false 并不让我感到惊讶;它比较的是两个对象的引用,而这两个引用并不相同。
但我很惊讶的是 Contains 方法返回了 true;显然它不仅仅是比较对象引用..它好像在比较 4 和 4 的未装箱值..但它如何知道要将对象拆箱以进行比较?我试图理解这里发挥作用的更大原则。

我认为 == 默认比较的是对象在内存中的引用,由于它们是两个不同的对象,所以它们在内存中有两个不同的位置。因此它们不相等。 - Hunter McMillen
6个回答

13

这个表达式

q.Contains(s)

正在寻找一个元素q,使得EqualityComparer<object>.Default.Equals(element, s)为真。对于装箱的基元类型,这将比较其值。


7

Contains方法在内部使用object.Equals方法来比较元素。它不使用==运算符。

Equals方法是虚拟的,而==运算符是静态的。这意味着==运算符将根据变量的编译时类型(而不是变量在运行时所持有的对象)确定要运行的代码。另一方面,虚拟方法不是静态绑定的。它根据变量值的运行时类型来确定要运行哪个Equals重载。


5
根据Contains文档:

使用默认的相等比较器,确定序列是否包含指定的元素。


2

Contains方法使用Equals方法,而不是==运算符。


3
实际上,它可能使用了 EqualityComparer<object>.Default.Equals - DeCaf
我知道一个虚拟的Equals方法(“默认比较器”)正在被调用来进行比较。但是,我想象中在我的情况下被调用的方法必须是Object.Equals,因为我对包含对象的类型进行了Contains操作。如果是这样的话,Object.Equals如何知道如何取消装箱内容并将它们作为整数进行比较呢? - Michael Ray Lovett
@DeCaf EqualityComparer<object>.Default 在内部使用 Object.Equals - MarcinJuraszek
@MichaelRayLovett 因为虚拟实数变量类型的Equals方法是在运行时检查的,这就是为什么会调用int.Equalt方法。 - MarcinJuraszek
我大致明白这个问题了,有什么好的信息来源可以更好地理解它吗? - Michael Ray Lovett

0

== 使用变量类型来确定要比较的相等性。

对于 object/object,它将执行引用相等性。

Contains 将使用虚拟的 Equals 方法,可能会被重载以进行值比较。在这种情况下,int 被写成这样。


== 使用变量的类型而不是对象的类型来确定调用哪个方法。 - Servy

-1

Contains 使用 object.Equals(object),对于 int 类型的对象,它们被实现为 4.equals(4) 为 true。而使用 == 进行比较时,只会进行引用比较。

另外需要注意的是:object.Equals(t, s) == true,因为 该方法 在引用相等失败时使用实例的 Equals 方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接