我实际上会说,对于任何结构,应该总是手动编写 Equals() 和 GetHashCode() 的覆盖以及实现 IEquatable<T> ,如果它's at all likely that it could be used by someone as a key, so I certainly wouldn' t使用它只是为了避免这样做 .
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; } }
}
3 回答
如果您唯一的问题是在
Dictionary<TKey,TValue>
中定义使用的相等性,那么您可以选择的另一个路径是实现IEqualityComparer<T>
. 这可以手动传递给字典构造函数,并负责TKey
值的相等比较,而无需修改密钥类型 .如果您有更复杂的定义复合值相等性的问题,那么我将专注于使复合值本身支持相等 . 是的,定义平等所需的全套方法是一种痛苦,但它主要是锅炉板代码 . 正确的做法比锅炉板代码看起来更麻烦更重要 .
我实际上会说,对于任何结构,应该总是手动编写
Equals()
和GetHashCode()
的覆盖以及实现IEquatable<T>
,如果它's at all likely that it could be used by someone as a key, so I certainly wouldn' t使用它只是为了避免这样做 .除了需要装箱之外,默认实现相当慢,因为它使用反射来检查字段 . 至少在一些框架版本中也存在一个错误(实现非常明智地优化为二进制比较,这样做会得到正确的结果,但不幸的是,在这种情况下错误判断,因此两个结构包含等效的
decimal
字段可能被视为不平等) .当需要快速复合时,建议不要使用
Tuple
.Tuple.Create()
可以轻松编写它们,Equals()
和GetHashCode()
的覆盖非常合理 .在某些情况下,它也适合使用匿名类作为键(当然只在给定方法的上下文中),这里
Equals()
和GetHashCode()
的覆盖也是非常合理的 .要创建这样的复合类,推荐的技术是从
Tuple<int, string, ...>
继承 .这样,您不必自己覆盖
GetHashCode
和Equals
,基类会为您完成 .您可以轻松地为每个字段提供有意义的get访问器 .
这也强制了不变性,这适用于字典键 .
至于性能,内置元组非常快 . 我发现自定义结构可以更快,但如果你真的需要每一个额外的性能,最好是直接将你的关键数据编码为int或long .