8

データ クラスを作成するたびに、IEquatable の実装に多くの時間を費やします。

私が書いた最後のクラスは次のようなものでした:

public class Polygon
{
    public Point[] Vertices { get; set; }
}

IEquatable の実装は非常に困難でした。確かに C#3.0/LINQ は大いに役立ちますが、頂点をシフトしたり、逆の順序にしたりできるため、Equals メソッドが非常に複雑になります。多くの単体テストと対応する実装の後、あきらめて、アプリケーションを三角形のみを受け入れるように変更しました。IEquatable の実装では、11 個の単体テストのみを完全にカバーする必要がありました。

Equals と GetHashCode の実装に役立つツールまたは手法はありますか?

4

2 に答える 2

8

ReSharper を使用して等価メンバーを生成します。必要に応じて、必要に応じて演算子を実装IEquatable<T>したり、オーバーライドしたりします(もちろん、これは決して行いませんが、とにかくクールです)。

Equals の実装には、 のオーバーライドとObject.Equals(Object)、厳密に型指定されたバリアント (不要な型チェックを回避できます) が含まれます。型の少ないバージョンは、型チェックを実行した後、強く型付けされたバージョンを呼び出します。厳密に型指定されたバージョンは、参照の等価性チェック ( Object.ReferenceEquals(Object,Object)) を実行してから、すべてのフィールドの値を比較します (つまり、ジェネレーターに含めるように指示したフィールドのみ)。

に関してGetHashCodeは、フィールドのGetHashCode値のスマート因数分解が結合されます (uncheckedコンパイラのオプションを使用する場合、オーバーフロー例外を回避するために使用しcheckedます)。フィールドの各値 (最初の値を除く) は、結合される前に素数で乗算されます。null にならないフィールドを指定することもでき、null チェックはすべて破棄されます。

を押してから「 Generate Equality Members」を選択すると、Polygonクラスに次のように表示されます。ALT+Insert

public class Polygon : IEquatable<Polygon>
{
    public Point[] Vertices { get; set; }

    public bool Equals(Polygon other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.Vertices, Vertices);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Polygon)) return false;
        return Equals((Polygon) obj);
    }

    public override int GetHashCode()
    {
        return (Vertices != null ? Vertices.GetHashCode() : 0);
    }
}

上記で説明した機能の一部は、フィールドが 1 つしかないため適用されません。配列の内容をチェックしていないことにも注意してください。

ただし、一般的に、ReSharper はほんの数秒で多くの優れたコードを生成します。そして、その機能は、ReSharper をこれほど素晴らしいツールにしている私のリストのかなり下の方にあります。

于 2009-06-07T22:44:15.387 に答える
2

アイテムの2つの配列を比較するために、SequenceEqual拡張メソッドを使用します。

一般的なEqualsとGetHashCodeに関しては、シリアル化に基づく手法が役立つ可能性があります。

再利用可能なGetHashCodeおよびDeepCopy関数にMemoryStreamおよびBinaryFormatterを使用する

于 2009-06-07T23:22:55.527 に答える