对Equals方法的几个常见误解

2019-12-30 11:04:16刘景俊

误解三:值类型的默认Equals实现是对两个对象进行逐位比较的。

有些人认为值类型的Equals默认实现就是通过比较两个对象在内存中的位表示,即如果所有的二进制位都相等,则说明这两个对象“等同”。这是不准确的。因为其实值类型的Equals默认实现是对值类型的每个字段都调用该字段类型的Equals方法,如果所有字段的Equals方法都返回true,则他们才可能相等。来看一个例子:
 

  1. class MyClass    {   
  2. public override bool Equals(object obj)    {   
  3. Console.WriteLine("MyClass的Equals方法被调用了。");    return true;   
  4. }    }   
  5. struct MyStruct    {   
  6. public MyClass Filed;    }   
  7. class Program    {   
  8. static void Main(string[] args)    {   
  9. MyStruct a;    MyStruct b;   
  10. a.Filed = new MyClass();    b.Filed = new MyClass();   
  11. Console.WriteLine(a.Equals(b));    }   
  12. }  
?

很显然,a和b拥有完全不同的二进制位表示。但是最终打印的结果是:
 

  1. MyClass的Equals方法被调用了。    True 
?

这说明值类型的默认实现是通过调用字段的Equals方法来确定两个对象是否相等,而不是通过比较他们的二进制位是否一致来确定的。

误解四:Equals是非常基本、非常常用的方法,所以其默认的实现不存在性能问题。

对于引用类型,Equals的默认实现很简单,仅仅需要判断两个引用是不是同一种类型、两个引用指向的是不是同一块内存就可以了。所以其性能也没有问题。但是对于值类型,Equals的任务就没有这么简单了。它需要对两个对象的所有字段都做出比较,即逐字段调用字段类型的Equals。