C# で正確で柔軟かつ高速な Equalsを実装する最善の方法について考えてみました。パフォーマンスのためには、特殊な Equals (実際のクラスのオブジェクトをパラメーターとして受け取る) が必要であると考えました。コードの重複を避けるために、一般的な Equals は特殊化された Equals を呼び出す必要があります。継承されたクラスであっても、null チェックは 1 回だけ実行する必要があります。
私は最終的にこのデザインを思いつきました:
class MyClass
{
public Int32 SomeValue1 = 1;
public Int32 SomeValue2 = 25;
// Ignoring GetHashCode for simplicity.
public override bool Equals(object obj)
{
return Equals (obj as MyClass);
}
public bool Equals(MyClass obj)
{
if (obj == null) {
return false;
}
if (!SomeValue1.Equals (obj.SomeValue1)) {
return false;
}
if (!SomeValue2.Equals (obj.SomeValue2)) {
return false;
}
return true;
}
}
class MyDerivedClass : MyClass
{
public Int32 YetAnotherValue = 2;
public override bool Equals(object obj)
{
return Equals (obj as MyDerivedClass);
}
public bool Equals(MyDerivedClass obj)
{
if (!base.Equals (obj)) {
return false;
}
if (!YetAnotherValue.Equals (obj.YetAnotherValue)) {
return false;
}
return true;
}
}
重要なアイデア:
- 「as」演算子の使用。このようにして、一般的な Equals で null をチェックする必要がなくなります。間違ったクラス タイプは null に縮小され、特殊化された Equals に分類されます。
- 派生クラスであっても、正確に 1 点で Null チェックを行います。
- 属性を次々に確認すると、明確な構造が得られます。
この概念に欠陥はありますか、それとも条件を逃しましたか?