Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

c# - How are Equals and GetHashCode implemented on anonymous types?

The Help says this:

Anonymous types are class types that derive directly from object, and that cannot be cast to any type except object. The compiler provides a name for each anonymous type, although your application cannot access it. From the perspective of the common language runtime, an anonymous type is no different from any other reference type.

If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.

Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

These things are true, but how? The reference source shows explicitly how objects are compared (ReferenceEquals) and a type that 'derives directly from object' cannot have this special behaviour. It doesn't match the behavour of Equals in ValueType either.

So how is it done? How can anonymous types override Equals() and GetHashCode() without any visible overrides?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The compiler generates the GetHashCode() and Equals() overrides for you. For example, from this code:

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

        Console.WriteLine(a);
    }
}

You can find the generated anonymous type in the compiled .exe, where the methods look like this (this is the output from dotPeek…there's also ToString()):

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

  [DebuggerHidden]
  public override bool Equals(object value)
  {
    var fAnonymousType0 = value as u003Cu003Ef__AnonymousType0<u003CTextu003Ej__TPar, u003CValueu003Ej__TPar>;
    return fAnonymousType0 != null && EqualityComparer<u003CTextu003Ej__TPar>.Default.Equals(this.u003CTextu003Ei__Field, fAnonymousType0.u003CTextu003Ei__Field) && EqualityComparer<u003CValueu003Ej__TPar>.Default.Equals(this.u003CValueu003Ei__Field, fAnonymousType0.u003CValueu003Ei__Field);
  }

  [DebuggerHidden]
  public override int GetHashCode()
  {
    return -1521134295 * (-1521134295 * 512982588 + EqualityComparer<u003CTextu003Ej__TPar>.Default.GetHashCode(this.u003CTextu003Ei__Field)) + EqualityComparer<u003CValueu003Ej__TPar>.Default.GetHashCode(this.u003CValueu003Ei__Field);
  }

Related reading:
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?

None of those directly address your question, but they do provide some relevant insights into the specific implementations of these overrides.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...