繁体   English   中英

词典中的复合键; 覆盖GetHashCode(),Equals等或使用结构?

[英]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, ...>继承。

这样,您不必自己覆盖GetHashCodeEquals ,基类会为您完成。

您可以轻松地为每个字段提供有意义的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM