EqualityComparer<T>.Default 誤解ですか?
-
11-12-2019 - |
質問
授業があります Person
, 、から Equals() メソッドを実装します。 IEquatable<Person>
(オーバーライドも Object.Equals
メソッド、今は GetHashcode() メソッドを無視しましょう)
class Person : IEquatable<Person>
{
public string Name { get; set; }
public bool Equals(Person other)
{
return this.Name == other.Name;
}
public override bool Equals(object obj)
{
var person = obj as Person;
return person != null && person.Name == Name;
}
}
じゃあ始めよう:
Person p1 = new Person() { Name = "a" };
Person p2 = new Person() { Name = "a" };
List<Person> lst1 = new List<Person>() { p1 };
List<Person> lst2 = new List<Person>() { p2 };
この行について話しましょう:
bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);
この部分を理解するのに問題があります:
EqualityComparer<Person>.Default
それを聞いたことがあります EqualityComparer<Person>.Default
クラスが実装されているかどうかを確認します IEquatable
- それはかかります Equals(Person other)
メソッドではなく、 Equals(object obj)
. ボクシングを避けるという利点がある
しかし
の Equals(Person other)
走ります 有無 EqualityComparer<Person>.Default
(IEquatableを実装しているため)
それで、私たちはボクシングとは何について話しているのでしょうか?ないよ!
唯一その時は Equals(object obj)
実行されるのは次の場合です:
bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);
しかし 私はプログラマーです!決して送信しません object
それが実際にあるとき Person
!
私には何が欠けているのでしょうか?ここでの利点を理解するのが困難です EqualityComparer<Object>.Default
. 。誰か私が間違っていることを証明する例を教えてください。
解決
通りかかった場合 null
2 番目のパラメータとして、または 2 番目の引数をまったく渡さない場合 (これは基本的に同じです)、SequenceEquals の実装は次の呼び出しを行います。 EqualityComparer<T>.Default
それ自体(逆コンパイル) Enumerable
これを見るには)。これは、提供するかどうかに違いが見られない理由を説明しています。 EqualityComparer<T>.Default
か否か。
したがって、最終的に 2 番目のパラメータは、等価比較子を使用する場合にのみ意味を持ちます。 以外の EqualityComparer<T>.Default
.
他のヒント
通過できること IEqualityComparer<object>.Default
の影響です 一般的な反変性, .NET 4で追加されました。
本質的に、 IEqualityComparer<BaseType>
いつでも使用できます IEqualityComparer<DerivedType>
は必須です。ここで、 DerivedType : BaseType
. 。以来 Person
から派生 Object
, 、これは、 IEqualityComparer<Object>
どこでも使用できます IEqualityComparer<Person>
が必要です。
答えは次のとおりです。 http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
値型の場合、パフォーマンスを向上させるために、常に IEquatable を実装し、Object.Equals(Object) をオーバーライドする必要があります。Object.Equals は値の型をボックス化し、リフレクションに依存して 2 つの値が等しいかどうかを比較します。Equals の実装と Object.Equals のオーバーライドはどちらも一貫した結果を返す必要があります。
Equals と GetHashCode をオーバーライドしない場合、実際には EqualityComparer.Default がそれを処理します。