1

複数の文字列キーを持つデータ構造を作成しようとしています。これを行うために、string[] 要素を使用して Dictionary を作成しようとしました。しかし、ContainsKey は期待どおりに機能していないようです。

Dictionary<string[], int> aaa = new Dictionary<string[], int>();
int aaaCount = 0;
aaa.Add(new string[] { string1, string2 }, aaaCount++);

if (!aaa.ContainsKey(new string[] { string1, string2 }))
{
    aaa.Add(new string[] { string1, string2 }, aaaCount++);
}

上記のコードを実行すると、aaa にエントリが 2 つあることがわかりますが、1 つしかないと思っていました。これは予想される動作ですか?ディクショナリに重複エントリがないことを確認するにはどうすればよいですか?

注:リストでも同じことを試しました(リストと結果は同じです-Containsメソッドはstring []では実際には機能しません)

4

4 に答える 4

2

string[]TKey として使用する場合はIEqualityComparer<string[]>、のコンストラクターにDictionary渡す必要があります。それ以外の場合、ディクショナリは標準比較を使用しTKey、その場合は参照string[]を比較するだけなのでstring[]、参照型です。IEqualityComparer を自分で実装する必要があります。次の方法で実行できます。

(実装は非常に単純です。出発点として提供します)

public class StringArrayComparer : IEqualityComparer<string[]>
{
    public bool Equals(string[] left, string[] right)
    {
        if (ReferenceEquals(left, right))
        {
            return true;
        }

        if ((left == null) || (right == null))
        {
            return false;
        }

        return left.SequenceEqual(right);
    }

    public int GetHashCode(string[] obj)
    {
        return obj.Aggregate(17, (res, item) => unchecked(res * 23 + item.GetHashCode()));
    }
}
于 2011-11-29T01:35:35.690 に答える
2

配列は参照型であるため、つまり、配列内の値に基づく等価性ではなく、参照(同一性) の等価性をチェックしているためです。同じ値で新しい配列を作成すると、配列自体は 2 つの異なるオブジェクトのままであるため、ContainsKeyfalse を返します。

辞書のキーとして配列を使用するのは少し...奇妙です。ここで何をマッピングしようとしていますか? おそらくもっと良い方法があります。

于 2011-11-29T01:22:00.743 に答える
2

IEqualityComparer<string[]>を作成して辞書のコンストラクターに渡す必要があります。

これは、キーを比較する方法を辞書に伝えます。
デフォルトでは、参照によってそれらを比較します。

于 2011-11-29T01:22:41.293 に答える
0

アプリケーションがサポートしている場合は、文字列配列を単一の文字列に結合する方がよい場合があります。

2 つの情報がコレクション内のレコードを一意に識別する多くのケースがあり、これらのケースでは、どちらの文字列にも含まれてはならない値 (つまり、Char(1)) を使用して 2 つの文字列を結合します。

通常、追加されるのはクラス インスタンスであるため、コレクションに追加するコードが 1 つのプロパティ (つまり CollectionKey) のチェックのみを行うように、クラスにキーの生成を指定させます。

于 2011-11-29T01:27:11.073 に答える