我尝试编写一个程序,其中Dictionary由List索引。 (相信我,我有,并且有选项,但我喜欢按列表编制索引)。有一个最小的工作(实际上不工作,只有一个最后一行是一个问题)例子:
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中有两个元素,但仍然无法通过正确的索引访问这些元素--- h [w]。我错了还是有什么奇怪的事情发生?
答案 0 :(得分:7)
您的应用程序的问题来自以下事实:
new List<String> { "a" } != new List<String> { "a" }
列表的等式检查以查看两个引用是否引用同一个实例。在这种情况下,他们没有。相反,您创建了两个具有相同元素的列表......这些列表并不能使它们相等。
您可以通过创建自定义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>());
答案 1 :(得分:2)
问题是List的索引,您索引的不是列表中的数据,而是基本上通过指向List的内存指针(即此List所在的内存地址)进行索引。 / p>
您在一个内存位置创建了一个列表,然后在不同的内存位置创建了一个完全不同的列表(即创建新实例时)。即使它们包含相同的数据,这两个列表也是不同的,这意味着您可以在字典中添加任意数量的列表。
一种解决方案不是按List索引,而是按字符串索引,并使用逗号分隔的List,其中包含列表中的所有数据作为索引。
答案 2 :(得分:1)
这对您不起作用,因为List<T>
的{{1}}和Equals
方法不会考虑列表的内容。如果要将对象集合用作键,则需要实现自己的集合类型,以覆盖集合中对象的相等性来覆盖GetHashCode
(可能使用{{ 3}}。)
答案 3 :(得分:1)
Dictionary类使用引用比较来查找指定的键,这就是为什么即使列表包含相同的项,它们也是不同的。