为什么即使变量是引用类型,Equals和ReferenceEquals方法的结果也不同

本文关键字:方法 ReferenceEquals 结果 Equals 变量 引用类型 为什么 | 更新日期: 2023-09-27 18:24:00

根据本msdn文档

如果当前实例是引用类型,则Equals(Object)方法测试引用相等性,并且对Equals)方法的调用等效于对ReferenceEquals方法的调用

那么,为什么以下代码会导致方法调用的两个不同结果Equals方法返回TrueReferenceEquals方法返回false,即使objobj1是引用类型,因为IsClass属性返回True。

using System;
                    
public class Program
{
    public static void Main()
    {
        var obj = new { a = 1, b = 1 };
        var obj1 = new { a = 1, b = 1 };
        
        Console.WriteLine("obj.IsClass: " + obj.GetType().IsClass);
        
        Console.WriteLine("object.ReferenceEquals(obj, obj1): " + object.ReferenceEquals(obj, obj1));
        
        Console.WriteLine("obj.Equals(obj1): " + obj.Equals(obj1));
    }
}

输出:

obj.IsClass:真

object.ReferenceEquals(obj,obj1):错误

obj.Equals(obj1):

为什么即使变量是引用类型,Equals和ReferenceEquals方法的结果也不同

objobj1引用了两个不同的对象,因此object.ReferenceEquals()将返回false。

Equals()返回true,因为编译器为匿名类型实现了Equals()。如果两个对象的所有属性都具有相同的值,则返回true。

所有匿名类型都有一个Equals覆盖,其工作方式为:

  1. 如果第一个对象为空,则如果第二个对象为零则返回true,否则返回false
  2. 如果第二个对象为null,则返回false
  3. 如果这两个对象的类型不同,则返回false(但所有具有相同属性的匿名对象都是相同类型的,并且在同一对象中具有相同的名称)
  4. 遍历每个属性,如果对两个对象为该属性所具有的值调用Equalsfalse,则返回false
  5. 返回true

(它们还有一个GetHashCode,它通过组合对每个属性的GetHashCode调用来工作)。

如果不是这样,那么GroupByDistinctUnion和类似的方法就不能使用匿名属性,因为这些方法中的每一个都需要相等的概念才能工作。

如果两个对象实际上是同一个对象,则ReferenceEquals通过返回true来工作,如果不是,则返回false

非匿名对象的默认值是Equals返回与ReferenceEquals相同的内容。如果它不是匿名的,并且需要其他东西,那么作者会提供Equals覆盖,并且在如何做到这一点上会有更大的灵活性