3

我正在使用包含字符串数组的字典列表。字典是通过 a 上的循环定义/填充的DataTable。在下面的代码中,测试评估为假(两次),有人可以告诉我为什么吗?

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

问题是您用作字典键的字符串数组进行对象比较,而不是内容比较。

为了支持这种类型的数据作为键,最简单的解决方案是使用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 回答
1

如果我错了,希望有人能纠正我,但我的理解是,当您调用 时ContainsKeyDictionary有一个私有方法(在 dotPeek 中探索),该方法用于确定您正在比较的对象是否相等。

根据您为键使用的类型,将根据 的各种实现进行不同的相等比较IEqualityComparer,这样可以根据您希望比较的类型运行最合适的比较。

您使用字符串数组作为键,因此您实际上是在检查数组对象本身的相等性,而不是它们的内容。因此,您ContainsKey返回 false 是完全正确的,您不是Dictionary在询问它是否包含与键相同的数组,而是在询问它是否包含不同的数组,而该数组恰好包含相同的内容。

IEqualityComparer GetHashCode例中的方法(一个数组)将基于对象的引用而不是内容返回一个哈希值。

如果你想要这种行为,神奇的 Skeet 先生IEqualityComparer<T>在这篇文章中为数组编写了一个自定义:

比较对象?

于 2013-07-28T00:08:57.483 回答