【问题标题】:How are Equals and GetHashCode implemented on anonymous types?Equals 和 GetHashCode 如何在匿名类型上实现?
【发布时间】:2025-12-10 08:05:01
【问题描述】:

帮助是这样说的:

匿名类型是直接从对象派生的类类型,并且 不能转换为除对象之外的任何类型。编译器提供了一个 每个匿名类型的名称,尽管您的应用程序无法访问 它。从公共语言运行时的角度来看,一个匿名的 type 与任何其他引用类型没有什么不同。

如果程序集中有两个或多个匿名对象初始化程序指定一个 具有相同顺序且具有 相同的名称和类型,编译器将对象视为 同一类型。它们共享相同的编译器生成的类型 信息。

因为匿名类型的 Equals 和 GetHashCode 方法是 根据 Equals 和 GetHashCode 方法定义 属性,相同匿名类型的两个实例仅当 它们的所有属性都是相等的。

这些事情都是真的,但如何呢?参考源明确显示了如何比较对象 (ReferenceEquals),并且“直接从对象派生”的类型不能具有这种特殊行为。它也不符合ValueTypeEquals 的行为。

那么它是如何完成的呢?匿名类型如何在没有任何可见覆盖的情况下覆盖 Equals()GetHashCode()

【问题讨论】:

    标签: c# equals anonymous-types gethashcode


    【解决方案1】:

    编译器会为您生成 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);
      }
    

    相关阅读:
    How does ToString on an anonymous type work?
    Why anonymous types Equals implementation compares fields?
    Equality for anonymous types
    Why is ValueType.GetHashCode() implemented like it is?

    这些都没有直接解决您的问题,但它们确实为这些覆盖的具体实现提供了一些相关的见解。

    【讨论】: