2

私はC#を初めて使用します。IEquatable同じと見なされるべき私のタイプのオブジェクトはそうではないので、おそらく私は適切に実装していません。

クラス:

class CompPoint : IComparable {
        public int X;
        public int Y;

        public CompPoint(int X, int Y) {
            this.X = X;
            this.Y = Y;
        }

   public override bool Equals(Object o) {
        if (!(o is CompPoint)) {
            throw new ArgumentException(String.Format("argument is not a CompPoint (%s given)", o));
        }
        CompPoint cp = (CompPoint)o;

        return this.X == cp.X && this.Y == cp.Y;
    }

    public override int GetHashCode() {
        int hash = base.GetHashCode(); // this is a problem. replace with a constant?
        hash = (hash * 73) + this.X.GetHashCode();
        hash = (hash * 73) + this.Y.GetHashCode();
        return hash;
    }
}

(これ以上にCompPoint、クラスであることを正当化するものがあります。)

次に、このテストは失敗します。

    [TestMethod()]
    public void compPointTest() {
        Assert.AreEqual(new CompPoint(0, 0), new CompPoint(0, 0));
    }

私は何を誤解していますか?Assert.AreEqual()参照の平等を使用していますか?私のEquals()機能がCompPoint台無しになっていますか?

この関数も失敗します:

    public void EqualsTest() {
        Assert.IsTrue(new CompPoint(1, 1).Equals(new CompPoint(1, 1)));
    }

この理由は、私がを使用してDictionaryいて、期待どおりに機能していないためです。

    [TestMethod()]
    public void dictCompPointTest() {
        IDictionary<CompPoint, int> dict = new Dictionary<CompPoint, int>();
        dict[new CompPoint(0, 0)] = 4;
        dict[new CompPoint(0, 0)] = 24;
        dict[new CompPoint(0, 0)] = 31;

        Assert.AreEqual(31, dict[new CompPoint(0, 0)]);
        Assert.AreEqual(1, dict.Count);
    }

テストは次のメッセージで失敗します:

テストメソッドShipAILabTest.BoardUtilsTest.dictCompPointTestが例外をスローしました:System.Collections.Generic.KeyNotFoundException:指定されたキーがディクショナリに存在しませんでした。

このテストは私の期待をカプセル化します。キーは毎回同じなので、値が上書きされることを期待しています。Dictionary平等をテストするために何を使用していますか?

更新: Thomasの提案に従って、等式関数を追加しました。これで、CompPoint比較テストが機能し、機能しdictCompPointTestます。

    public override bool Equals(Object o) {
        if (!(o is CompPoint)) {
            throw new ArgumentException(String.Format("argument is not a CompPoint (%s given)", o));
        }
        CompPoint cp = (CompPoint)o;

        return this.X == cp.X && this.Y == cp.Y;
    }

不思議なことに、このテストはまだ失敗します:

   [TestMethod()]
    public void dictCPTest2() {
        IDictionary<CompPoint, int> dict = new Dictionary<CompPoint, int>();
        dict[new CompPoint(2, 2)] = 2;
        dict[new CompPoint(2, 2)] = 2;

        Assert.AreEqual(1, dict.Count);
    }

キーが。の場合もテストは失敗しますが、キーがの場合は失敗しnew CompPoint(4, 1)ませんnew CompPoint(0, 1)。なぜこれが一部の値で機能し、他の値では機能しないのでしょうか。

さらに謎:ハッシュコード関数はかなりうまく機能していないようです。このテストは失敗します:

    [TestMethod()]
    public void hashCodeTest() {
                int x = 0;
                int y = 0;
                Assert.AreEqual(new CompPoint(x, y).GetHashCode(), new CompPoint(x, y).GetHashCode());    
    }

ハッシュコード関数は上にリストされています。ここでの問題は何ですか?CompPoint2つのオブジェクトが同じハッシュコードを持つべきではありませんか?多分私の呼び出しbase.getHashCode()は問題ですか?

4

2 に答える 2

3

Assert.AreEqualを使用するだけObject.Equalsで、ではないと思いますIEquatable<T>.EqualsEqualsしたがって、のロジックを反映するようにオーバーライドする必要がありますIEquatable<T>.Equals

または、次を使用することもできますAssert.IsTrue

IEquatable<CompPoint> p1 = new CompPoint(0, 0);
IEquatable<CompPoint> p2 = new CompPoint(0, 0);
Assert.IsTrue(p1.Equals(p2));

インターフェイスが明示的に実装されているため、 p1とp2をIEquatable<CompPoint>次のように宣言していることに注意してください。これIEquatable<CompPoint>.Equalsは、ではなく呼び出されるようにするためです。Object.Equals

編集:ちなみに、CompPointクラスではなく構造体として宣言することをお勧めします。そうすれば、値の型がフィールド値に従って比較されるため、何も実装する必要がありません。

于 2010-02-07T23:35:28.553 に答える