Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当项被强制转换为对象时,为什么equals的工作方式不同?_C# - Fatal编程技术网

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

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

当我将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.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,您将看到它正在执行。