1

我正在尝试使用具有多个字符串键的数据结构。为此,我尝试使用 string[] 元素创建字典。但是 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 中有两个条目,而我只期待一个。这是预期的行为吗?如何确保字典中没有重复的条目?

注意:我也对列表进行了同样的尝试(列表和结果是相同的 - Contains 方法实际上不适用于字符串 [])

4

4 回答 4

2

因为数组是引用类型,也就是说,您正在检查引用(身份)相等性,而不是基于数组中的值的相等性。当您创建具有相同值的新数组时,数组本身仍然是两个不同的对象,因此ContainsKey返回 false。

使用数组作为字典键有点……奇怪。你想在这里映射什么?可能有更好的方法来做到这一点。

于 2011-11-29T01:22:00.743 回答
2

您需要创建一个IEqualityComparer<string[]>并将其传递给字典的构造函数。

这告诉字典如何比较键。
默认情况下,它通过引用比较它们。

于 2011-11-29T01:22:41.293 回答
2

如果要用作 TKey ,string[]则应传递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 回答
0

如果您的应用程序支持,您最好将字符串数组组合成一个字符串。

我们有很多这样的情况,两条信息唯一地标识集合中的一条记录,在这些情况下,我们使用一个永远不应出现在任何一个字符串中的值(即 Char(1))来连接这两个字符串。

因为它通常是一个被添加的类实例,所以我们让类指定密钥的生成,这样添加到集合中的代码只需要担心检查单个属性(即 CollectionKey)。

于 2011-11-29T01:27:11.073 回答