1

ディクショナリがリストによってインデックス付けされるプログラムを作成しようとしています。(私を信頼してください。はい、オプションがありますが、リストによるインデックス作成が好きです)。最小限の動作 (実際には動作せず、最後の 1 行だけが問題です) の例があります。

using System;
using System.Collections.Generic;

namespace test
{
    class Program
    {
    static void Main(string[] args)
    {
        Dictionary<List<String>, int> h = new Dictionary<List<string>,int>();

        List<String> w = new List<string> {"a"};
        h.Add(w, 1);

        w = new List<string>{"b"};
        h.Add(w,2);

        w = new List<string>{"a"};

        int value = 0;
        h.TryGetValue(w, out value);
        Console.WriteLine(value+" "+h[w]);
    }
}

このプログラムをデバッグすると、h に 2 つの要素があることがはっきりとわかりますが、これらの要素には正しいインデックス (h[w]) を介してアクセスすることはできません。私は間違っていますか、それとも何か奇妙なことが起こっていますか?

4

4 に答える 4

7

あなたのアプリの問題は、次の事実から拡張されます。

new List<String> { "a" } != new List<String> { "a" }

リストの等価性は、2 つの参照が同じインスタンスを参照しているかどうかを確認します。この場合、そうではありません。代わりに、同じ要素を持つ 2 つのリストを作成しましたが、それらは等しくなりません。

カスタム Equality Comparer を作成することで問題を解決できます。

public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
{
    public bool Equals(List<T> list1, List<T> list2)
    {
        return list1.SequenceEquals(list2);
    }

    public int GetHashCode(List<T> list)
    {
        if(list != null && list.Length > 0)
        {
            var hashcode = list[0].GetHashCode();
            for(var i = 1; i <= list.Length; i++)
                hashcode ^= list[i].GetHashCode();

            return hashcode;
        }

        return 0;
    }
}

そして、それを Dictionary コンストラクターに渡します。

Dictionary<List<String>, int> h = 
    new Dictionary<List<string>,int>(new ListEqualityComparer<String>());
于 2011-11-10T14:57:19.653 に答える
2

問題はリストによるインデックスです。インデックスを作成するのはリスト内のデータではありませんが、基本的にリストへのメモリポインター(つまり、このリストが配置されているメモリアドレス)によってインデックスを作成しています。

あるメモリ ロケーションで 1 つのリストを作成した後、別のメモリ ロケーションでまったく別のリストを作成しました (つまり、新しいインスタンスを作成したとき)。同じデータが含まれていても、2 つのリストは異なります。これは、辞書に必要なだけ追加できることを意味します。

1 つの解決策は、List でインデックスを作成するのではなく、String でインデックスを作成し、リスト内のすべてのデータを含むカンマ区切りの List をインデックスとして使用することです。

于 2011-11-10T14:56:53.443 に答える
1

Dictionary クラスは、参照比較を使用して指定されたキーを探します。そのため、リストに同じ項目が含まれていても、それらは異なります。

于 2011-11-10T14:57:38.693 に答える
1

とメソッドはリストの内容を考慮しないList<T>ため、これはうまくいきません。オブジェクトのコレクションをキーとして使用する場合は、コレクション内のオブジェクトの等価性をチェックするような方法でオーバーライドする独自のコレクション型を実装する必要があります(おそらく を使用します)。EqualsGetHashCodeEqualsEnumerable.SequenceEqual

于 2011-11-10T14:57:33.327 に答える