オブジェクトが正しいかどうかをチェックするのと同じくらい簡単なことを実現することは、.NET の設計では少し難しいと思います。
構造体用
1) 実装しIEquatable<T>
ます。パフォーマンスが著しく向上します。
2)あなたはEquals
今あなた自身を持っているので、オーバーライドGetHashCode
し、さまざまな同等性チェックのオーバーライドと一貫性を保つためにobject.Equals
.
3)構造体をorで意図せずに別の構造体と同一視するとコンパイラが警告するため、オーバーロード==
と!=
演算子を宗教的に行う必要はありませんが、メソッドとの一貫性を保つためにそうすることをお勧めします。==
!=
Equals
public struct Entity : IEquatable<Entity>
{
public bool Equals(Entity other)
{
throw new NotImplementedException("Your equality check here...");
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
return Equals((Entity)obj);
}
public static bool operator ==(Entity e1, Entity e2)
{
return e1.Equals(e2);
}
public static bool operator !=(Entity e1, Entity e2)
{
return !(e1 == e2);
}
public override int GetHashCode()
{
throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
}
}
授業のために
MS から:
ほとんどの参照型は、Equals をオーバーライドする場合でも、等価演算子をオーバーロードしないでください。
私に==
は、値の等価性のように感じられ、Equals
メソッドの構文糖衣のように感じられます。書くa == b
ことは、書くことよりもはるかに直感的ですa.Equals(b)
。参照の等価性をチェックする必要があることはめったにありません。物理オブジェクトの論理表現を扱う抽象レベルでは、これを確認する必要はありません。==
と のセマンティクスが異なると、Equals
実際には混乱する可能性があると思います。そもそもそれは==
価値の平等とEquals
参照(または のようなより良い名前)の平等のためであるべきだったと思います。ここでは、MS ガイドラインを真剣に受け止めたくありません。それは、私にとって自然ではないという理由だけでなく、過負荷が大きな害を及ぼさないためでもあります。それは、非ジェネリックをオーバーライドしないのとは異なりますIsSameAs
==
Equals
または、フレームワークはどこにも使用されず、私たち自身が使用する場合にのみ使用さGetHashCode
れるため、噛み付く可能性があります。オーバーロードしない==
ことで得られる唯一の本当の利点は、私が制御できないフレームワーク全体の設計との一貫性です。そして、それは確かに大きなことなので、悲しいことに私はそれに固執します.==
!=
参照セマンティクス (可変オブジェクト) を使用
1) と をオーバーライドEquals
しGetHashCode
ます。
2) 実装IEquatable<T>
は必須ではありませんが、あると便利です。
public class Entity : IEquatable<Entity>
{
public bool Equals(Entity other)
{
if (ReferenceEquals(this, other))
return true;
if (ReferenceEquals(null, other))
return false;
//if your below implementation will involve objects of derived classes, then do a
//GetType == other.GetType comparison
throw new NotImplementedException("Your equality check here...");
}
public override bool Equals(object obj)
{
return Equals(obj as Entity);
}
public override int GetHashCode()
{
throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
}
}
値セマンティクス (不変オブジェクト) を使用
これはトリッキーな部分です。気をつけないと簡単にズレてしまいます..
1) と をオーバーライドEquals
しGetHashCode
ます。
2) オーバーロード==
と!=
を一致させEquals
ます。nulls で機能することを確認してください。
2) 実装IEquatable<T>
は必須ではありませんが、あると便利です。
public class Entity : IEquatable<Entity>
{
public bool Equals(Entity other)
{
if (ReferenceEquals(this, other))
return true;
if (ReferenceEquals(null, other))
return false;
//if your below implementation will involve objects of derived classes, then do a
//GetType == other.GetType comparison
throw new NotImplementedException("Your equality check here...");
}
public override bool Equals(object obj)
{
return Equals(obj as Entity);
}
public static bool operator ==(Entity e1, Entity e2)
{
if (ReferenceEquals(e1, null))
return ReferenceEquals(e2, null);
return e1.Equals(e2);
}
public static bool operator !=(Entity e1, Entity e2)
{
return !(e1 == e2);
}
public override int GetHashCode()
{
throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
}
}
クラスを継承できる場合は、特に注意してください。そのような場合、基本クラスのオブジェクトが派生クラスのオブジェクトと等しくなるかどうかを判断する必要があります。理想的には、派生クラスのオブジェクトが等価チェックに使用されない場合、基本クラス インスタンスは派生クラス インスタンスと等価である可能性があり、そのような場合、基本クラスのType
ジェネリックで等価をチェックする必要はありません。Equals
一般に、コードを複製しないように注意してください。再利用を容易にするためのテンプレートとして、一般的な抽象基本クラス (IEqualizable<T>
またはそのようなもの) を作成することもできましたが、悲しいことに C# では、追加のクラスから派生することができなくなりました。