字符串数组查找

时间:2013-07-27 23:38:16

标签: c# list dictionary datatable

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

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? 

2 个答案:

答案 0 :(得分:1)

如果我错了,希望有人会纠正我,但我的理解是,当你致电ContainsKey时,Dictionary有一个私人方法(在dotPeek中探索),这决定了你比较的对象是否相同。

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

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

本例中的IEqualityComparer GetHashCode方法(数组)将根据对象的引用返回哈希值,而不是内容。

如果您想要这种行为,那么神奇的Skeet先生已在此帖子中为数组编写了一个自定义IEqualityComparer<T>

Compare Objects?

答案 1 :(得分: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。