7

GetHashCodeカスタム等価チェックを実装するときにオーバーライドすることの重要性を知っています-そのためにインターフェイスを実装しました。また、ここで説明したIEquality<T>ジェネリックと非ジェネリックの違いも知っています。オーバーライドするポイントはありますか?すべてがジェネリックに分類されませんか?Equals Equals(object t)Equals(T t)

public override int GetHashCode() //required for hashsets and dictionaries
{
    return Id;
}

public bool Equals(T other) //IEquatable<T> here
{
    return Id == other.Id;
}

public override bool Equals(object obj) //required??
{
    return Equals(obj as T);
}
4

3 に答える 3

10

封印されていない型は を実装すべきではありませんIEquatable<T>。派生型がそれを正しく実装することを保証する (またはその可能性を高める) 唯一の方法は、IEquatable<T>.Equals(T)を呼び出すように実装することだからObject.Equals(Object)です。の全体的な目的は、物事を比較する前にIEquatable<T>変換して CPU 時間を浪費するのを避けることであるため、 を呼び出す実装は、インターフェースが実装されていない場合に達成されるデフォルトの動作よりも速く何もできませんでした。ObjectObject.Equals(Object)

シールされたクラス型は、実装することでパフォーマンスがわずかに向上する場合がありIEquatable<T>ます。推奨されるスタイルはObject.Equals(Object)、パラメーターを にキャストしようとすることTです。キャストが成功した場合は、IEquatable<T>.Equals実装を使用します。それ以外の場合は返品しfalseます。同じオブジェクト インスタンスを渡したときに、異なる結果が得られるべきIEquatable.Equals(T)ではありません。Object.Equals(Object)

構造体型は、sealed クラス型と同じパターンを使用できます。失敗したキャストは を返すことができないため、キャストを試みる方法は少し異なりますnullが、パターンは同じである必要があります。構造体が変更インターフェースを実装する場合 (たとえばList<T>.Enumerator、 を実装する構造体の場合のようにIEnumerator<T>)、等値比較の適切な動作は少しあいまいです。

ところで、IComparable<T>IEquatable<T>は互いに独立していると見なされるべきであることに注意してください。when X.CompareTo(Y)is zeroX.Equals(Y)が true を返す場合がよくありますが、一部の型は自然な順序付けを持ち、2 つのものが互いにランク付けされずに異なる場合があります。たとえば、 aと aNamedThing<T>を組み合わせた型があるとします。そのようなタイプは、名前の自然な順序付けをサポートしますが、必ずしもそうではありません。名前は一致するが が異なる 2 つのインスタンスは、 for を返しますが、 forを返します。このため、 が変更されていない場合、オーバーライドはオーバーライドを必要としません。stringTTT0CompareTofalseEqualsIComparableGetHashCodeEquals

于 2012-12-06T19:47:49.573 に答える
6

必ずオーバーライドする必要Equals(object t)があります。そうしないと、そのオーバーロードが使用されたときに誤った結果が得られる可能性があります。が呼び出されるオーバーロードであると想定することはできませんEquals(T other)

オーバーライドしない場合、参照の等価性が使用されます。つまり、次のようなものは false を返します。

myObject1.Id = 1;
myObject2.Id = 1;

myObject1.Equals((object)myObject2); // false!

もう 1 つの考えられる問題は、クラスの継承に関するものです。自分の型を継承する型と比較すると、簡単に失敗する可能性があります。

于 2012-12-06T10:35:46.777 に答える
3

From msdn:

If you implement IEquatable, you should also override the base class implementations of Object.Equals(Object) and GetHashCode so that their behavior is consistent with that of the IEquatable.Equals method. If you do override Object.Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. In addition, you should overload the op_Equality and op_Inequality operators. This ensures that all tests for equality return consistent results.

I could have done a better google search too. Here's a good article on msdn blogs by JaredPar on the subject.

In short, overriding Equals(object obj):

Needed for the static Equals(object obj1, object obj2) method on object class, or for Contains(object item) on ArrayList instance etc..

Accepting this since the link is more thorough on the subject. Thanks to Oded too..

于 2012-12-06T10:51:35.500 に答える