19

このテストは失敗します:

using Microsoft.VisualStudio.TestTools.UnitTesting;        

[TestMethod()]
        public void dictEqualTest() {
            IDictionary<string, int> dict = new Dictionary<string, int>();
            IDictionary<string, int> dictClone = new Dictionary<string, int>();

        for (int x = 0; x < 3; x++) {
            dict[x.ToString()] = x;
            dictClone[x.ToString()] = x;
        }

        Assert.AreEqual(dict, dictClone); // fails here
        Assert.IsTrue(dict.Equals(dictClone)); // and here, if the first is commented out
        Assert.AreSame(dict, dictClone); // also fails
    }

私はDictionary作品がどのように機能するかについて何か誤解していますか?

.equals()参照の同等性をチェックしようとせずに、Javaに相当するものを探しています。

4

6 に答える 6

24

Object.EqualsMSDN docoからわかるように、ディクショナリクラスはメソッドをオーバーライドしません。

http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

指定されたオブジェクトが現在のオブジェクトと等しいかどうかを判別します。

単体テストを行っていることを確認すると、Assertクラスは2つのコレクションが同じであるかどうかをテストするためのテストメソッドを提供する必要があります。

Microsoft単体テストフレームワークはCollectionAssert、コレクションを比較するためのクラスを提供します。

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.collectionassert_members%28VS.80%29.aspx

EDIT DictionaryはICollectionインターフェイスを実装していますが、それが機能するかどうかを確認できますか?このオーバーロードを使用して、2つのディクショナリエントリを比較する必要がある場合があります。

EDIT Hmm IDictionaryは実装されていませんがICollection、これは少し面倒です。ただし、これは機能します(ハックではありますが)。

IDictionary<string, int> dict = new Dictionary<string, int>();
IDictionary<string, int> dictClone = new Dictionary<string, int>();

for(int x = 0; x < 3; x++) {
    dict[x.ToString()] = x;
    dictClone[x.ToString()] = x;
}

CollectionAssert.AreEqual((System.Collections.ICollection)dict, (System.Collections.ICollection)dictClone);

上記のアプローチはのインスタンスで機能しますがDictionary、を返すメソッドをテストしているIDictionary場合、実装が変更されると失敗する可能性があります。Dictionary私のアドバイスは、代わりに使用するようにコードを変更することですIDictionaryIDictionary読み取り専用ではないため、concreateの代わりにそれを使用することでそれほど多くを隠すことはありませんDictionary)。

于 2010-02-08T00:56:12.753 に答える
13

単体テストの観点からこれを修正する方法に特に関心がある場合:

これを試して

CollectionAssert.AreEquivalent(dict.ToList(), dictClone.ToList());

説明

IDictionary には、.Net 3.5 以降で利用可能な拡張メソッドなどがあり.ToList()ます。これにより、ディクショナリが KeyValuePair のコレクションに変換され、簡単に比較できますCollectionAssert.AreEquivalent

かなり役立つエラー メッセージも表示されます。使用例:

IDictionary<string, string> d1 = new Dictionary<string, string> {
    { "a", "1"}, {"b", "2"}, {"c", "3"}};

IDictionary<string, string> d2 = new Dictionary<string, string> {
    {"b", "2"}, { "a", "1"}, {"c", "3"}}; // same key-values, different order

IDictionary<string, string> d3 = new Dictionary<string, string> {
    { "a", "1"}, {"d", "2"}, {"c", "3"}}; // key of the second element differs from d1

IDictionary<string, string> d4 = new Dictionary<string, string> {
    { "a", "1"}, {"b", "4"}, {"c", "3"}}; // value of the second element differs from d1

CollectionAssert.AreEquivalent(d1.ToList(), d2.ToList());
//CollectionAssert.AreEquivalent(d1.ToList(), d3.ToList()); // fails!
//CollectionAssert.AreEquivalent(d1.ToList(), d4.ToList()); // fails!

// if uncommented, the 2 tests above fail with error:
//   CollectionAssert.AreEquivalent failed. The expected collection contains 1
//   occurrence(s) of <[b, 2]>. The actual collection contains 0 occurrence(s).     
于 2012-06-18T14:17:23.060 に答える
7

問題は次のコード行にあります。

Assert.AreEqual(dict, dictClone)

等しくないオブジェクト参照を比較しています。

于 2010-02-08T00:54:33.750 に答える
4

2 つのシーケンスが等しい項目をチェックする拡張メソッドを使用しました

public static bool CheckForEquality<T>(this IEnumerable<T> source, IEnumerable<T> destination)
{
    if (source.Count() != destination.Count())
    {
        return false;
    }

    var dictionary = new Dictionary<T, int>();

    foreach (var value in source)
    {
        if (!dictionary.ContainsKey(value))
        {
            dictionary[value] = 1;
        }
        else
        {
            dictionary[value]++;
        }
    }

    foreach (var member in destination)
    {
        if (!dictionary.ContainsKey(member))
        {
            return false;
        }

        dictionary[member]--;
    }

    foreach (var kvp in dictionary)
    {
        if (kvp.Value != 0)
        {
            return false;
        }
    }

    return true;
}
于 2010-02-08T01:20:59.083 に答える
1

参照型がどのように機能するかを完全に理解していません。

Dictionaryをオーバーライドしませんobject.Equals()。したがって、参照の同等性を使用します。基本的に、両方の参照が同じインスタンスを指している場合、それらは等しく、そうでない場合はそうではありません。

于 2010-02-08T00:55:00.537 に答える