![](/img/trans.png)
[英]Use “external” GetHashCode and Equals for Dictionary
[英]Composite key in Dictionary; override GetHashCode(), Equals etc or use structs?
我有很多字典,其中键是几个不同值(主要是字符串和整数)的组合。 我是否将这些键实现为类(并覆盖GetHashCode()
, Equals()
等)或者我是否使用struct
?
ReSharper可以轻松完成覆盖,但代码看起来很糟糕。 是否有使用结构的性能影响?
如果您唯一的问题是在Dictionary<TKey,TValue>
定义使用的相等性,那么您可以选择的另一个路径是实现IEqualityComparer<T>
。 这可以手动传递给字典构造函数,并负责TKey
值的相等比较,而无需修改密钥类型。
如果您有更复杂的定义复合值相等性的问题,那么我将专注于使复合值本身支持相等。 是的,定义平等所需的全套方法是一种痛苦,但它主要是锅炉板代码。 正确的做法比锅炉板代码看起来更麻烦更重要。
我实际上会说,对于任何结构,应该总是手动编写Equals()
和GetHashCode()
的重写以及实现IEquatable<T>
,如果它可能被某人用作键,那么我当然不会用它只是为了避免这样做。
除了需要装箱之外,默认实现相当慢,因为它使用反射来检查字段。 至少在一些框架版本中也存在一个错误(实现非常明智地优化为二进制比较,这样做会给出正确的结果,但不幸的是,在这种情况下会错误判断,因此两个结构包含等效的decimal
字段可能被视为不平等)。
当需要快速复合时除了作为复合键之外对系统没有任何意义,我建议使用Tuple
。 Tuple.Create()
可以很容易地编写它们,而Equals()
和GetHashCode()
的覆盖是非常合理的。
在某些情况下,使用匿名类作为键也是合适的(当然只在给定方法的上下文中),这里Equals()
和GetHashCode()
的覆盖也是非常合理的。
要创建这样的复合类,推荐的技术是从Tuple<int, string, ...>
继承。
这样,您不必自己覆盖GetHashCode
和Equals
,基类会为您完成。
您可以轻松地为每个字段提供有意义的get访问器。
public class CompositeKey : Tuple<string, int>
{
public CompositeKey(string name, int age)
: base(name, age)
{
}
public string Name { get { return Item1; } }
public int Age { get { return Item2; } }
}
这也强制了不变性,这适用于字典键。
至于性能,内置元组非常快。 我发现自定义结构可以更快,但如果你真的需要每一个额外的性能,最好是直接将你的关键数据编码为int或long。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.