为什么当项被强制转换为对象时,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
一个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,因为运行时检查它们的值。这是所有!