C# 当项被强制转换为对象时,为什么equals的工作方式不同?
当我将int和float转换为object并比较它们时,等式总是false。为什么?C# 当项被强制转换为对象时,为什么equals的工作方式不同?,c#,C#,当我将int和float转换为object并比较它们时,等式总是false。为什么? 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.WriteLin
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
当您将值类型强制转换为对象时,它实际上被放入堆中,==在该点比较引用,这将是false。(简化)因为
等于
比较对象引用的地址,并且两个数字存储在不同的位置。如果比较这两种值类型,则Equals的行为正确,因为它已被float、int、string和其他类型覆盖。您将int和float装箱到一个对象,这意味着它们作为引用进行比较。因为它们不是对同一对象的引用,所以它们不相等
参见A
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);
这些转换只是方法和运算符重载解析所需的普通转换
其余的行都不涉及隐式转换,因此它们比较两种不同的类型,即使按值进行比较(所有Equals
调用都是这种情况),也会得到false
的结果。这就是为什么在装箱的int
值上使用Equals
会返回true
,因为这是按值比较相同类型的两个值
在这种情况下:
Console.WriteLine(obi == obf);
它甚至不尝试比较数值,而是比较装箱对象的引用。由于存在两个不同的引用,因此结果为
false
——即使两个值的类型均为int
,结果也是如此,因为它们被分配给不同的内存单元。
仅当两个对象是同一对象时,才为。
在float和int部分,当您测试这两个变量时,您会得到一个true,因为运行时会检查它们的值。
就这些 声明两个对象时,它们引用不同的内存位置:
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的默认实现支持的引用相等
引用类型和值类型的位相等。参考文献
相等意味着比较的对象引用引用
同样的目标。按位相等意味着要比较的对象具有
相同的二进制表示
其他人已经解释了为什么
==
不能在对象上按预期工作
关于编辑:oi1.Equals(oi2)
起作用,因为Equals
是一个虚拟函数,因此被调用,其返回值定义如下:
如果obj是Int32的实例且等于该实例的值,则为true;否则,错误
这也解释了为什么
obi.Equals(obf))
返回false:obf
不是Int32的实例。要了解更多关于框选值类型时发生的情况,Shivprasad在这里非常简洁地描述了这一点:
由于要将值类型装箱到对象,因此现在要执行引用相等。由于它们现在位于示例中的不同内存位置,因此将返回false。隐式转换是否在编译时得到处理?@CharlesLambert:Yes。看一下IL,您将看到它正在执行。