集合作为字典中的关键

时间:2013-08-09 07:19:17

标签: c# dictionary

我有这样的字典:

var dic = Dictionary<Collection<MyObject>, string>

然后我添加一个这样的条目:

dic.Add(myObjColl, "1");

其中myObjColl包含单个条目

在第二次运行中,我尝试向dic添加另一个条目,其中myObjColl有两个条目(其中一个与第一次运行中的条目相同),并且我得到一个异常,即密钥已经存在。

我在这里缺少什么?我希望字典键是一个集合,当然两个具有不同条目数的集合不能相同。

编辑: 发生的事情是myObjColl在foreach之外初始化并且在第二次迭代期间更新了。所以我认为是一个带有两个条目的新集合实际上是旧的一个条目集合,并添加了一个额外的条目。

详细说明我的问题:

我有一组产品行对象。每个都有一个产品标识对象,由一组键值对组成:

Collection<ProductKeyValuePair> productIdentification;
myProductRow.ProductIdentification = productIdentification;

然后我必须构建另一个ProductKeyValuePairs集合,定义每个产品行对象的“所有者”(一个产品行对象可以有多个所有者),我需要将每个所有者添加到对应的procuct行对象。传统的多对多,其中公共密钥是KeyValuePairs的集合。

很难解释,但它实际上取决于在大型机上运行的旧系统返回的遗留数据,并且很可能存储在某种分层数据库中: - /

3 个答案:

答案 0 :(得分:6)

字典中的键在执行键盘作用时应该是不可变的。如果您执行任何操作来更改GetHashCode()Equals(object)的值,您将获得未定义的行为。

(如果Collection未实现GetHashCode()Equals(object)使用其包含的成员,则只会通过引用容器对象本身进行比较。

答案 1 :(得分:2)

它没有检查集合的内容。

它只是使用myObjColl(通过ref)作为键。

注意:将集合作为关键是非常罕见的。键通常是字符串(或整数)。

答案 2 :(得分:0)

要使像集合这样的引用类型成为字典中的键,通常需要将自定义比较器(IEqualityComparer<TKey>)传递给字典的constructor。否则使用类的默认Equals / GetHashCode实现,通常没有值语义(即string是类似于值的引用类型的样本。)

过度简化的收集比较器(无空检查,仅比较计数)和以下用法:

class ListSameByCount<T> : EqualityComparer<List<T>>
{

  public override bool Equals(List<T> b1, List<T> b2)
  {
    return b1.Count() == b2.Count();
  }

  public override int GetHashCode(List<T> b1)
  {
    return b1.Count().GetHashCode();
  }
}

var dictionary = new Dictionary<List<int>, int>(new ListSameByCount<int>());

注意:集合通常不适合字典中的键,因为它们可以变异(添加/删除/更改项目),结果哈希代码会更改,字典将无法找到密钥。