Equals 和 GetHashCode 如何在匿名类型上实现?
How are Equals and GetHashCode implemented on anonymous types?
帮助是这样说的:
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.
这些都是真的,但是怎么办呢?参考源明确显示了对象是如何比较的 (ReferenceEquals
) 以及 'derives directly from object' 不能具有这种特殊行为的类型。它也不符合 ValueType
中 Equals
的行为。
那么它是怎么做到的呢?匿名类型如何在没有任何可见覆盖的情况下覆盖 Equals()
和 GetHashCode()
?
编译器为您生成 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?
None 其中直接解决了您的问题,但它们确实提供了一些关于这些覆盖的具体实现的相关见解。
帮助是这样说的:
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.
这些都是真的,但是怎么办呢?参考源明确显示了对象是如何比较的 (ReferenceEquals
) 以及 'derives directly from object' 不能具有这种特殊行为的类型。它也不符合 ValueType
中 Equals
的行为。
那么它是怎么做到的呢?匿名类型如何在没有任何可见覆盖的情况下覆盖 Equals()
和 GetHashCode()
?
编译器为您生成 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?
None 其中直接解决了您的问题,但它们确实提供了一些关于这些覆盖的具体实现的相关见解。