2

当我们装箱两种值类型(它们是不同的类型但兼容以比较值,例如:int 和 short)并尝试调用 Equals 方法时,即使值相同,也会给出 false。

情况1:

int a = 5;
short b = 5;
var ob_a = (object) a;
var ob_b = (object) b;
var result = a == b; // true
var result_for_objects = ob_a.Equals(ob_b); // false

另一方面,当两个值类型相同时,Equals 返回实际值比较结果。

案例二:

int a = 5;
int b = 5;
var ob_a = (object) a;
var ob_b = (object) b;
var result = a == b; // true
var result_for_objects = ob_a.Equals(ob_b); // true

我比较了这两种情况的反汇编代码,但它是相同的,我找不到任何区别。

            var result = a == b;
012404DE  mov         eax,dword ptr [ebp-40h]  
012404E1  cmp         eax,dword ptr [ebp-44h]  
012404E4  sete        al  
012404E7  movzx       eax,al  
012404EA  mov         dword ptr [ebp-50h],eax  
            var result_for_objects = ob_a.Equals(ob_b);
012404ED  mov         ecx,dword ptr [ebp-48h]  
012404F0  mov         edx,dword ptr [ebp-4Ch]  
012404F3  mov         eax,dword ptr [ecx]  
012404F5  mov         eax,dword ptr [eax+28h]  
012404F8  call        dword ptr [eax+4]  
012404FB  mov         dword ptr [ebp-5Ch],eax  
012404FE  movzx       eax,byte ptr [ebp-5Ch]  
01240502  mov         dword ptr [ebp-54h],eax  
  1. 如果装箱对象中的值类型不同,实际上调用的是哪个 Equals 方法?
  2. 当装箱对象内的两种值类型相同时,它如何调用该值类型的 Equals 方法?
4

1 回答 1

5

变量的类型保存在对象中。

例如:

Console.Write(ob_a.GetType().ToString());   // will give you System.Int32
Console.Write(ob_b.GetType().ToString());   // will give you System.Int16

它还通过方法提供了不同的哈希码:GetHashCode()

如果您将短变量转换为 int 或其他方式,它将是相等的......所以基本上问题在于不同的变量类型。

这是两个问题的答案:http ://www.ikriv.com/dev/dotnet/ObjectEquality.html

由于对 Equals() 的调用是虚拟的,x.Equals(y) 将调用的方法的确切版本由 x 的动态类型决定,这通常在编译时是未知的。另请注意,与 a==b 不同,表达式 x.Equals(y) 本质上是不对称的。只有 x 指示将调用哪个版本的 Equals()。y 在这件事上绝对没有发言权。

于 2017-08-08T04:51:10.137 回答