==タイトルにあるように、演算子をオーバーライドする必要がありますか?方法はどう.Equals()ですか?足りないものはありますか?
6 に答える
msdnからの例
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex c && this == c;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
IEquatable<T>も実装する必要があります。フレームワーク設計ガイドラインからの抜粋は次のとおりです。
値型にIEquatableを実装してください。値型のObject.Equalsメソッドはボクシングを引き起こし、デフォルトの実装はrefectionを使用するため、あまり効率的ではありません。IEquatable.Equalsは、はるかに優れたパフォーマンスを提供し、ボクシングを引き起こさないように実装できます。
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
IEquatable.Equalsを実装する場合は、Object.Equalsをオーバーライドする場合と同じガイドラインに従ってください。Object.Equalsのオーバーライドに関する詳細なガイドラインについては、セクション8.7.1を参照してください。
残念ながら、他のエントリにコメントするのに十分な評判がありません。だから私はここにトップソリューションへの可能な強化を投稿しています。
私が間違っている場合は訂正してください、しかし上記の実装
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
大きな欠陥があります。私が言及しているのは
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
XORingは対称であるため、Complex(2,1)とComplex(1,2)は同じhashCodeを提供します。
おそらく、次のようなものを作成する必要があります。
public override int GetHashCode()
{
return re.GetHashCode() * 17 ^ im.GetHashCode();
}
ほとんどの場合、構造体にEqualsとGetHashcodeを実装することは避けられます。これは、ビット単位のコンテンツと参照メンバーのリフレクションを使用した値型のコンパイラによる自動実装があるためです。
その投稿を見てください: データストアの構造体/クラスに最適なのはどれですか?
したがって、使いやすさのために、==と!=を実装することもできます。
ただし、ほとんどの場合、EqualsとGetHashcodeの実装を回避できます。
EqualsとGetHashCodeを実装する必要がある場合は、考慮したくないフィールド用です。
たとえば、Age of aPersonやinstantSpeedof a carのように時間の経過とともに変化するフィールド(同じ場所の辞書でオブジェクトを見つけたい場合は、オブジェクトのIDを変更しないでください)
よろしく、最高のコード
2つの基本的な違いは、==演算子が静的であるということです。つまり、呼び出す適切なメソッドはコンパイル時に決定されますが、Equalsメソッドはインスタンスで動的に呼び出されます。
構造体は拡張できないため(構造体は別の構造体から継承できないため)、構造体の場合はそれほど重要ではありませんが、両方を定義するのがおそらく最善の方法です。
完全を期すために、Equalsメソッドをオーバーロードすることもお勧めします。
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
Equals(Object obj)メソッドの入力引数のボクシングが発生しないため、これは実際の速度の向上です。
値型を使用するためのいくつかのベストプラクティス:
- それらを不変にする
- Equals(オブジェクトを引数として取るもの)をオーバーライドします。
- オーバーロード同じ値型の別のインスタンスを取得するために等しい(例:* Equals(Complex other));
- オーバーロード演算子==および!=;
- GetHashCodeをオーバーライドする
これはこの投稿から来ています:http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/