使用自定义对象作为字典键 [英] Use custom object as Dictionary Key

查看:70
本文介绍了使用自定义对象作为字典键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用自定义对象作为Dictionary键,主要是这样的:(我不能使用.net 4.0,所以我没有元组)

I want to use a custom object as a Dictionary key, mainly, I have something like this: (I can't use .net 4.0 so I don't have tuples)

class Tuple<A, B> : IEquatable<Tuple<A,B>>
{
  public A AValue { get; set; }
  public B BValue { get; set; }

  public Tuple(A a, B b){ AValue = a; BValue = b; }

  public bool Equals(Tuple<A, B> tuple)
  {
    return tuple.AValue.Equals(AValue) && tuple.BValue.Equals(BValue);
  }

  public bool Equals(object o)
  {
  return this.Equals(o as Tuple<A,B>);
  }
}

然后我要做类似的事情。

I then do something like this.

  var boolmap = new Dictionary<Tuple<bool, bool>, string>();
  boolmap.Add(new Tuple<bool,bool>(true, true), "A");
  boolmap.Add(new Tuple<bool,bool>(true, false), "B");
  boolmap.Add(new Tuple<bool,bool>(false, true), "C");
  boolmap.Add(new Tuple<bool,bool>(false, false), "D");
  var str = boolmap[new Tuple<bool,bool>(true, false)];

我在最后一行收到KeyNotFound异常。为什么是这样 ?我实现IEquatable还不够吗?

I get a KeyNotFound exception at the last line. Why is this ? Isn't it enough I implement IEquatable ?

谢谢

推荐答案

您还需要覆盖 GetHashCode()(最好还覆盖 Equals())。您本来相等的对象返回一个不同的哈希码,这意味着在查找时找不到该键。

You also need to override GetHashCode() (and preferably also Equals()). Your otherwise-equal object is returning a different hash code, which means that the key is not found when looked up.

GetHashCode()合同规定,当两个对象的返回值相等时,两个对象的返回值必须相等。这是问题的根源。您的课程不符合此要求。合同没有规定如果值不相等则该值必须不同,但这将提高性能。 (如果所有对象都返回相同的哈希码,则从性能角度来看,您也可以使用平面列表。)

The GetHashCode() contract specifies that the return value from two objects MUST be equal when the two objects are considered equal. This is the root of your problem; your class does not meet this requirement. The contract does not specify that the value must be different if they are not equal, but this will improve performance. (If all of the objects return the same hash code, you may as well use a flat list from a performance perspective.)

在您的情况下,一个简单的实现可能是:

A simple implementation in your case might be:

public override int GetHashCode()
{
    return AValue.GetHashCode() ^ BValue.GetHashCode();
}

请注意,测试 AValue 或 BValue null 。 (这会有些复杂,因为您不限制通用类型 A B ,所以您不能只比较 null 的值-例如,类型可以是值类型。) 1

Note that it might be a good idea to test if AValue or BValue are null. (This will be somewhat complicated since you don't constrain the generic types A and B, so you cannot just compare the values to null -- the types could be value types, for example.)1

将要用作字典键的类设为不可变也是一个好主意。如果更改了用作键的对象的值,则字典将表现出奇怪的行为,因为该对象现在位于不属于该对象的存储桶中。

It's also a good idea to make classes you intend to use as dictionary keys immutable. If you change the value of an object that is being used as a key, the dictionary will exhibit weird behavior since the object is now in a bucket where it doesn't belong.

1 请注意,您可以使用 EqualityComparer< A> .Default.GetHashCode(AValue) (对于 BValue code>),因为这样就不需要空检查。

1 Note that you could make use of EqualityComparer<A>.Default.GetHashCode(AValue) (and similar for BValue) here, as that will eliminate the need for a null check.

这篇关于使用自定义对象作为字典键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆