匿名类型中如何实现Equals和GetHashCode方法?

11
帮助文档中说明:
匿名类型是从对象直接派生的类类型,不能转换为除了对象以外的任何类型。编译器为每个匿名类型提供一个名称,但您的应用程序无法访问它。从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有区别。
如果同一程序集中的两个或多个匿名对象初始化程序指定了相同顺序且具有相同名称和类型的属性序列,则编译器将对象视为同一类型的实例。它们共享相同的编译器生成的类型信息。
因为匿名类型上的Equals和GetHashCode方法是根据属性的Equals和GetHashCode方法定义的,所以同一匿名类型的两个实例仅在它们的所有属性都相等时才相等。
这些内容是正确的,但是如何实现的呢?参考源代码明确显示了如何比较对象(ReferenceEquals),而“直接派生自对象”的类型则无法具有此特殊行为。这也与ValueType中的Equals行为不匹配。
那么是如何做到的?匿名类型如何在没有可见覆盖的情况下覆盖Equals()和GetHashCode()呢?
1个回答

15

编译器为您生成GetHashCode()Equals()的重写。例如,从以下代码:

class Program
{
    static void Main(string[] args)
    {
        var a = new { Text = "foo", Value = 17 };

        Console.WriteLine(a);
    }
}

您可以在编译后的.exe文件中找到生成的匿名类型,其中方法看起来像这样(这是来自dotPeek的输出…还有ToString()):

  [DebuggerHidden]
  public override string ToString()
  {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("{ Text = ");
    stringBuilder.Append((object) this.\u003CText\u003Ei__Field);
    stringBuilder.Append(", Value = ");
    stringBuilder.Append((object) this.\u003CValue\u003Ei__Field);
    stringBuilder.Append(" }");
    return ((object) stringBuilder).ToString();
  }

  [DebuggerHidden]
  public override bool Equals(object value)
  {
    var fAnonymousType0 = value as \u003C\u003Ef__AnonymousType0<\u003CText\u003Ej__TPar, \u003CValue\u003Ej__TPar>;
    return fAnonymousType0 != null && EqualityComparer<\u003CText\u003Ej__TPar>.Default.Equals(this.\u003CText\u003Ei__Field, fAnonymousType0.\u003CText\u003Ei__Field) && EqualityComparer<\u003CValue\u003Ej__TPar>.Default.Equals(this.\u003CValue\u003Ei__Field, fAnonymousType0.\u003CValue\u003Ei__Field);
  }

  [DebuggerHidden]
  public override int GetHashCode()
  {
    return -1521134295 * (-1521134295 * 512982588 + EqualityComparer<\u003CText\u003Ej__TPar>.Default.GetHashCode(this.\u003CText\u003Ei__Field)) + EqualityComparer<\u003CValue\u003Ej__TPar>.Default.GetHashCode(this.\u003CValue\u003Ei__Field);
  }

相关阅读:
匿名类型的 ToString 方法是如何工作的?
为什么匿名类型的 Equals 实现会比较字段?
匿名类型的相等性
为什么 ValueType.GetHashCode() 的实现方式是这样的?

虽然这些文章并没有直接回答您的问题,但它们提供了一些有关这些重载方法具体实现的相关见解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接