3

文字列配列を含む辞書のリストを扱っています。辞書は、 a のループを介して定義/入力されますDataTable。次のコードでは、test が false (2 回) と評価されますが、その理由を教えていただけますか?

List<Dictionary<string[], int>> mydix = new List<Dictionary<string[], int>>();

mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 

string[] s = {"tree"};
mydix[1].Add(s, 1);
bool test = mydix[1].ContainsKey(s); // This evaluates to true, which I understand
var entry= mydix[1][s]; // This is 1

DataTable dt=new DataTable();
dt.Columns.Add("test");
dt.Rows.Add(new string[] {"key"});            
mydix[2].Add(dt.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 2);
test = mydix[2].ContainsKey(new string[] { "key" }); // Why does this evaluate to false?

// Here is an example with an array with two elements
DataTable dt2 = new DataTable(); 
dt2.Columns.Add("test");
dt2.Columns.Add("test2");    
string[] t={"tree1","tree2"}; 
dt2.Rows.Add(t);
mydix[0].Add(dt2.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 3);
test = mydix[0].ContainsKey(t); // Why does this evaluate to false? 
4

2 に答える 2

1

私が間違っている場合は誰かが私を修正してくれることを願っていますが、 を呼び出すとContainsKeyDictionary比較するオブジェクトが等しいかどうかを判断するために実行されるプライベートメソッド (dotPeek で探索) があることを理解しています。

キーに使用しているタイプに応じて、 のさまざまな実装に基づいて異なる等値比較が行われますIEqualityComparer。このようにして、比較するタイプに基づいて最も適切な比較を実行できます。

文字列配列をキーとして使用しているため、本質的には、配列オブジェクトの内容ではなく、配列オブジェクト自体の等価性をチェックしています。ContainsKeyしたがって、false を返しているのは完全に正しいDictionaryです。キーと同じ配列が含まれているかどうかを尋ねているのではなく、たまたま同じ内容を含んでいる別の配列が含まれているかどうかを尋ねているのです。

この場合のIEqualityComparer GetHashCodeメソッド (配列) は、コンテンツではなく、オブジェクトの参照に基づいてハッシュを返します。

この動作が必要な場合は、Skeet 氏IEqualityComparer<T>がこの投稿で配列のカスタムを書いた魔法を使用してください。

オブジェクトを比較しますか?

于 2013-07-28T00:08:57.483 に答える
1

問題は、ディクショナリのキーとして使用している文字列配列が、コンテンツの比較ではなく、オブジェクトの比較を行うことです。

このタイプのデータをキーとしてサポートするための最も簡単な解決策は、IEqualityComparerを使用することです。

まず、比較子を作成します (これはサンプルです。追加のサニティ チェックとロジックが必要になります)。

    private class ArrayComparer : IEqualityComparer<string[]>
    {
        public bool Equals(string[] item1, string[] item2)
        {
            if (item1[0] == item2[0])
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public int GetHashCode(string[] item)
        {
            return item[0].GetHashCode();
        }

次に、辞書のインスタンス化を変更して、この新しい比較子を使用します。

    mydix.Add(new Dictionary<string[], int>(new ArrayComparer()));
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 

これが完了すると、両方のテストで true が返されます。

于 2013-07-28T00:11:13.997 に答える