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

时间:2010-03-15 15:30:02

标签: c# .net dictionary struct value-type

我有很多字典,其中键是几个不同值(主要是字符串和整数)的组合。我是否将这些密钥作为类实现(并覆盖GetHashCode()Equals()等),还是使用struct代替?

ReSharper可以轻松完成覆盖,但代码看起来很糟糕。是否有使用结构的性能影响?

3 个答案:

答案 0 :(得分:3)

如果你唯一的问题是定义在Dictionary<TKey,TValue>中使用的相等性,那么你可以选择另一个路径来实现IEqualityComparer<T>。这可以手动传递给字典构造函数,并在不修改密钥类型的情况下处理TKey值的相等比较。

如果您有更复杂的定义复合值相等性的问题,那么我将专注于使复合值本身支持相等。是的,定义平等所需的全套方法是一种痛苦,但它主要是锅炉板代码。正确的做法比锅炉板代码看起来更麻烦更重要。

答案 1 :(得分:1)

我实际上会说,对于任何结构,应始终手动编写Equals()GetHashCode()的覆盖以及实施IEquatable<T>,如果完全可能的话可以被某人用作关键,所以我当然不会用它来避免这样做。

除了需要装箱之外,默认实现相当慢,因为它使用反射来检查字段。至少在一些框架版本中也存在一个错误(实现非常明智地优化为二进制比较,这样做会得到正确的结果,但不幸的是在这种情况下错误判断,因此两个结构包含等价的{{1 }}字段可能被认为是不相等的。)

当需要快速复合时,除了作为复合键之外,对系统没有任何意义,我建议使用decimalTuple可让您轻松撰写这些内容,Tuple.Create()Equals()的覆盖非常合理。

在某些情况下,也可以使用匿名类作为键(仅在给定方法的上下文中),这里GetHashCode()Equals()的覆盖也很合理

答案 2 :(得分:0)

要创建这样的复合类,建议的方法是从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。