代码之家  ›  专栏  ›  技术社区  ›  CodingInsomnia

字典中的复合键;重写gethashcode()、equals等还是使用结构?

  •  4
  • CodingInsomnia  · 技术社区  · 14 年前

    我有很多字典,其中的键是由几个不同的值(主要是字符串和整数)组成的组合。我是否将这些键实现为类(并重写 GetHashCode() , Equals() 等等)还是我用 struct 相反?

    Resharper使重写变得容易,但代码看起来很糟糕。使用结构是否会影响性能?

    3 回复  |  直到 11 年前
        1
  •  3
  •   JaredPar    14 年前

    如果您唯一的问题是在 Dictionary<TKey,TValue> 然后您可以选择的另一个路径是实现 IEqualityComparer<T> . 这可以手动传递给字典构造函数,并处理 TKey 不修改键类型的值。

    如果您有为复合值定义相等性的更一般的问题,那么我将着重于使复合值本机支持相等性。是的,定义实现平等所必需的全套方法是一件痛苦的事情,但它主要是锅炉板代码。正确理解这一点比锅炉盘代码看起来是否凌乱更重要。

        2
  •  1
  •   Jon Hanna    13 年前

    实际上,对于任何结构,都应该手动编写 Equals() GetHashCode() 以及实施 IEquatable<T> 如果它有可能被某人用作钥匙,那么我当然不会仅仅为了避免使用它。

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

    当需要一个快速的复合键时,除了作为复合键之外,它对系统没有任何意义,我建议使用 Tuple . Tuple.Create() 使其易于组合,以及 等于() 获取哈希代码() 相当合理。

    在某些情况下,也可以将匿名类用作键(当然,只能在给定方法的上下文中使用),这里是 等于() 获取哈希代码() 也相当合理。

        3
  •  0
  •   Eldritch Conundrum    11 年前

    要创建这样的复合类,建议使用继承自 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。

    推荐文章