为什么(object)0==(object)0与((object)1)不同.等于((object)0)

本文关键字:object 等于 不同 为什么 | 更新日期: 2024-10-19 06:58:50

为什么以下表达式不同?

[1]  (object)0 == (object)0 //false
[2]  ((object)0).Equals((object)0) // true

实际上,我完全可以理解[1],因为.NET运行时可能会box整数,并开始比较引用。但为什么[2]不同呢?

为什么(object)0==(object)0与((object)1)不同.等于((object)0)

调用行为不同的原因是它们绑定到非常不同的方法。

==大小写将绑定到静态引用相等运算符。创建了两个独立的盒装int值,因此它们不是相同的引用。

在第二种情况下,您绑定到实例方法Object.Equals。这是一个虚拟方法,它将向下过滤到Int32.Equals,并检查一个装箱的整数。这两个整数值都是0,因此它们是相等的

当您将int值0(或任何其他值类型)强制转换为object时,该值被装箱object的每个强制转换都会产生一个不同的框(即不同的对象实例)。object类型的==运算符执行引用比较,因此它返回false,因为左侧和右侧不是同一实例。

另一方面,当您使用Equals(这是一个虚拟方法)时,它使用实际装箱类型的实现,即Int32.Equals,由于两个对象具有相同的值,因此返回true。

==操作符是静态的,不是虚拟的。它将运行object类定义的确切代码(`object是操作数的编译时类型),无论任何一个对象的运行时类型如何,都将进行引用比较。

Equals方法是一种虚拟实例方法。它将运行(第一个)对象的实际运行时类型中定义的代码,而不是object类中的代码。在这种情况下,对象是int,因此它将执行值比较,因为这是int类型为其Equals方法定义的。

Equals()方法是虚拟的
因此,它总是调用具体的实现,即使调用站点被广播到objectint覆盖Equals()以按值进行比较,因此可以获得值比较。

==使用:Object.ReferenceEquals

CCD_ 26对该值进行比较。

object.ReferenceEquals方法比较参考文献。分配对象时,除了对象在内存堆上的数据外,还会收到一个引用,该引用还包含一个指示其内存位置的值。

object.Equals方法比较对象的内容。它首先检查引用是否相等,对象也是如此。ReferenceEquals。但随后它调用派生的Equals方法来进一步测试相等性。请参阅:

   System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b);  //returns true

C#运算符使用令牌==来表示两个不同的运算符:静态可重载比较运算符和不可重载引用比较运算符。当遇到==令牌时,它首先检查是否存在适用于操作数类型的相等测试重载。如果是这样,它将调用该重载。否则,它将检查这些类型是否适用于引用比较运算符。如果是,它将使用该运算符。如果两个运算符都不适用于操作数类型,则编译将失败。

代码(Object)0不仅将Int32上转换为Object:与所有值类型一样,Int32实际上代表两种类型,其中一种描述值和存储位置(如文字零),但不派生自任何内容,另一种描述堆对象并派生自Object;因为只有后一种类型可以向上转换为Object,所以编译器必须创建后一种新的堆对象。每次调用(Object)0都会创建一个新的堆对象,因此==的两个操作数是不同的对象,每个操作数独立地封装Int32值0。

Object没有为equals运算符定义任何可用的重载。因此,编译器将无法使用重载的相等测试运算符,并将重新使用引用相等测试。因为==的两个操作数引用不同的对象,所以它将报告false。第二个比较之所以成功,是因为它询问Int32的一个堆对象实例是否等于另一个。因为该实例知道与另一个不同实例相等意味着什么,所以它可以回答true

两种检查都不同。第一个检查身份,第二个检查。一般来说,如果两个术语指的是同一个对象,那么它们是相同的。这意味着他们是平等的。如果两项的值相同,则它们是相等的。

就编程而言,身份通常被引用相等所混淆。如果指向两项的指针相等(!),则它们所指向的对象完全相同。但是,如果指针不同,它们所指向的对象的值仍然可以相等。在C#中,可以使用静态Object.ReferenceEquals成员检查身份,而使用非静态Object.Equals成员检查相等性。由于要将两个整数强制转换为对象(称为"boxing",btw),因此object的运算符==将执行第一次检查,默认情况下会映射到Object.ReferenceEquals并检查标识。如果显式调用非静态Equals成员,则动态调度会导致对Int32.Equals的调用,从而检查相等性。

这两个概念相似,但并不相同。起初,它们可能看起来令人困惑,但微小的差异非常重要!想象两个人,即"爱丽丝"answers"鲍勃"。他们俩都住在一所黄色的房子里。基于这样的假设,爱丽丝和鲍勃住在一个地区,那里的房子只有颜色不同,他们可能都住在不同的黄色房子里。如果你比较一下这两个家,你会发现它们完全一样,因为它们都是黄色的!然而,他们并不共享同一个家,因此他们的房子是相等的,但不是相同的子里。

注意:一些语言正在定义===运算符来检查身份。