1

重複の可能性:
参照型の 2 つのインスタンスを比較するための「ベスト プラクティス」とは?

アプリケーション用にこのカスタム クラスがあります。このクラスには 2 つのインスタンス (A と B) があり、比較しようとしています。ただし、問題があります。IEquatable<T>オーバーライドされたメソッドを使用して、この比較を行うためのインターフェイスを実装して いますEquals

Equalsメソッドは関数を呼び出しますが、ReferenceEqualsこれは動作が正しくありません。

テストケースは次のとおりです。

ケース 1: A と B は異なるインスタンスであり、異なるデータが含まれています..ReferenceEquals言う: それらは異なります (これは正しいです!)

ケース 2: A と B は異なるインスタンスですが、B は A の変数値を使用してインスタンス化されました (つまり、A と B の両方にまったく同じデータが含まれています!) ..ReferenceEquals言う: それらは異なります (これは間違っています!)

ケース 3: A と B が同じインスタンスである (つまり、A が 2 回渡されるなどEquals (A, A))ReferenceEqualsと言う: それらは同じです (これは正しいです!)

では、ケース 2 の結果も正しいものにするにはどうすればよいでしょうか。

IEquatable<T>が実装されているクラス:

namespace DBtestApp1
{
    class QuantityBasedDiscount : IEquatable<QuantityBasedDiscount>
    {
        public string pType { get; set; }
        public string pSubType { get; set; }
        public DataTable quantityDiscountsDT { get; set; }

        public QuantityBasedDiscount()
        {
            pType = "";
            pSubType = "";
            quantityDiscountsDT = new DataTable();
        }

        public QuantityBasedDiscount(string iProdType, string iProdSubType, DataTable iQuantitiesDT)
        {
            pType = iProdType;
            pSubType = iProdSubType;
            quantityDiscountsDT = iQuantitiesDT;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(Object obj)
        {

            var other = obj as QuantityBasedDiscount;
            if (other == null) return false;

            return Equals(other);
        }

        public bool Equals(QuantityBasedDiscount other)
        {
            if (other == null)
            {
                return false;
            }

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            return false;
        }
    }
}

メソッドを呼び出すコードEquals(ここではケース 2 用に構成):

private bool AnyUnsavedChanges()
{
    QuantityBasedDiscount copyB = new QuantityBasedDiscount(copyA.pType, copyA.pSubType, copyA.quantityDiscountsDT);

    if (copyA.Equals(copyB))
    {
         return false; //They are the same!
    }
    else
    {
         return true; //They are NOT the same!
    }

}

では、このコードの問題は何ですか?

4

2 に答える 2

2

正確な重複ではありませんが、ここにすべての答えがあります:参照型の 2 つのインスタンスを比較するための「ベスト プラクティス」とは? . そのスレッドから Konrad の回答が提供されたスニペットを取得して、間違いを犯さないようにしてください。


要するに、あなたはそれを間違っています。Equalsジェネリックメソッドで実際の値を比較していません。さらに、メソッド==内で演算子を呼び出すのは安全ではありません。Equals次のようにします。

public override int GetHashCode()
{
    return pType.GetHashCode() ^ pSubType.GetHashCode() ^ quantityDiscountsDT.GetHashCode();
    //or something similar, but fast.
}

public bool Equals(QuantityBasedDiscount other)
{
   if (ReferenceEquals(null, other))
    {
        return false;
    }

    if (ReferenceEquals(this, other))
    {
        return true;
    }

    return pType == other.pType && pSubType == other.pSubType && 
           quantityDiscountsDT == other.quantityDiscountsDT;
}

DataTable フィールドが変更されている場合、これでも一貫性のない結果が得られる可能性があります。==すべては、演算子が DataTable に対してどのように実装されているかに依存します。それをさらに制御するには、独自の DataTable を派生させる必要があります。

==さらに、!=演算子もオーバーロードしたい場合があります。すべてについては、提供されたリンクを確認してください。

于 2012-12-23T19:27:51.717 に答える
0

Equals と GetHashCode をオーバーライドする必要があります。構文が必要な場合は、'==' および '!=' 演算子もオーバーロードする必要があります。Equals のオーバーライドでは、まず ReferenceEquals が true を返すかどうかを確認し、そうでない場合はオブジェクトの内容を比較できます。

個人的には、そのような場合は ReferenceEquals を使用しないことを好みます。

于 2012-12-23T15:37:31.770 に答える