参照型のデフォルトの等価比較子は参照等価でありtrue
、2 つのオブジェクト参照が同じインスタンスを指している (つまり、単一のnew
ステートメントで作成された) 場合にのみ返されます。これは、値の等価性をテストする値型とは異なり、true
すべてのデータ フィールドが等しい場合に返されます (この場合の 2 つのように)。詳細:等値比較 (C# プログラミング ガイド)。
この動作を変更する場合はIEquatable<T>
、インスタンスのプロパティが等しいかどうかを比較するように、型にジェネリック インターフェイスを実装する必要があります。その後、Distinct
オペレーターはこの実装を自動的に選択し、期待される結果をもたらします。
編集IEquatable<Person>
:クラスのサンプル実装は次のとおりです。
public class Person : IEquatable<Person>
{
public int Id { get; set; }
public int Name { get; set; }
public bool Equals(Person other)
{
if (other == null)
return false;
return Object.ReferenceEquals(this, other) ||
this.Id == other.Id &&
this.Name == other.Name;
}
public override bool Equals(object obj)
{
return this.Equals(obj as Person);
}
public override int GetHashCode()
{
int hash = this.Id.GetHashCode();
if (this.Name != null)
hash ^= this.Name.GetHashCode();
return hash;
}
}
and演算子のオーバーライドに関するガイドラインから(強調を追加):==
!=
デフォルトでは、オペレーター==
は、2 つの参照が同じオブジェクトを示しているかどうかを判別することにより、参照の同等性をテストします。==
したがって、参照型は、この機能を得るために演算子を実装する必要はありません。型が不変である場合、つまり、インスタンスに含まれるデータを変更できない場合、演算子をオーバーロード==
して参照の等価性ではなく値の等価性を比較すると便利な場合があります。同じ値を持っています。不変でない型でoperator をオーバーライドすることはお勧めできません。==