为什么当项被强制转换为对象时,equals的工作方式不一样?

本文关键字:equals 工作 方式 不一样 对象 转换 为什么 | 更新日期: 2023-09-27 18:12:47

当我将int和float转换为object并比较它们时,相等总是假的。为什么?

        float f = 0.0f;
        int i = 0;
        Console.WriteLine(f.Equals(i)); // true
        Console.WriteLine(i.Equals(f)); // false
        Console.WriteLine(i == f); // true
        Console.WriteLine("----------------");
        object obf = f;
        object obi = i;
        Console.WriteLine(obf.Equals(obi)); // false
        Console.WriteLine(obi.Equals(obf)); // false
        Console.WriteLine(obi == obf); // false
        Console.WriteLine("----------------");

更新:对于同一类型

则不是这样。
        int i1 = 1;
        int i2 = 1;
        object oi1 = i1;
        object oi2 = i2;
        Console.WriteLine(oi1.Equals(oi2)); // true
        Console.WriteLine(oi2.Equals(oi1)); // true

为什么当项被强制转换为对象时,equals的工作方式不一样?

一个float只等于另一个float,一个int只等于另一个int。唯一返回true的行是这些:

Console.WriteLine(f.Equals(i));
Console.WriteLine(i == f);

在这两种情况下,i的值都隐式地转换为float的值,因此它们等价于:

Console.WriteLine(f.Equals((float) i));
Console.WriteLine((float) i == f);

这些转换只是方法和操作符重载解析所需的普通转换。

其余的行都不涉及隐式转换,所以它们比较的是两种不同的类型,即使按值比较也会得到false的结果(所有Equals调用都是这种情况)。这就是为什么在装箱的int上使用Equals会使返回true,因为这是比较两个相同类型的值

在本例中:

Console.WriteLine(obi == obf);

它甚至没有尝试比较数值——它比较的是引用对于被装箱的对象。因为有两个不同的引用,所以结果是false——即使两个值都是int类型也是如此。

其他人已经解释了为什么==不能像预期的那样在你的对象上工作。

关于你的编辑:oi1.Equals(oi2)工作,因为Equals是一个虚函数,因此Int32.Equals(object)被调用,其返回值定义如下:

true如果obj是Int32类型的实例并且等于这个实例的值;否则,

这也解释了为什么obi.Equals(obf))返回false: obf不是Int32的实例

您将int和float包装为一个对象,这意味着它们作为引用进行比较。因为它们不是对同一对象的引用,所以它们不相等。

见http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx

为了更好地理解将值类型框起来会发生什么,Shivprasad在这里非常简洁地描述了这一点:

装箱和拆箱

由于您将值类型装箱到对象,因此您现在正在执行引用相等。由于它们现在位于示例中的不同内存位置,因此将返回false。

当你声明了两个对象,它们引用了不同的内存位置:

object obf = f;         // this simplified as new float(f)
object obi = i;         // this simplified as new int(i)

,但尝试下面的方法,让一个对象引用另一个对象:

obf = obi;
Console.WriteLine(obf.Equals(obi));

MSDN,对象。=方法

Equals的默认实现支持引用类型,以及值类型的按位相等。参考相等意味着被比较的对象引用引用相同的对象。按位相等意味着被比较的对象具有相同的二进制表示。

当您将值类型强制转换为object时,它实际上被放入堆中,并且==在此时比较引用,这将为false。(简化)

因为Equals比较的是对象引用的地址,而这两个数字存储在不同的位置。如果你比较两种值类型,Equals的行为是正确的,因为它已经覆盖了float, int, string和其他类型。

因为它们被分配到不同的内存单元格。只有当两个对象是相同的对象时,它们才=。在float和int部分,当你测试这两个变量时,你会得到一个true,因为运行时检查它们的值。这是所有!