【问题标题】:C#: optimizing dictionary access (hash in key structures)C#:优化字典访问(键结构中的散列)
【发布时间】:2010-06-20 23:47:58
【问题描述】:

所以,我需要在 C# 中创建一个结构,它将作为一个(相当大的)字典的键,如下所示:

private readonly IDictionary<KeyStruct, string> m_Invitations;

问题是,我真的需要一个结构作为键,因为只能通过两个单独的数据项来识别条目,其中一个可以是空字符串(不仅是空的!)。

我需要在结构上实现什么?您将如何创建哈希?哈希冲突(偶尔)会严重影响性能还是可以忽略不计?

我问是因为这是“内循环”代码。

【问题讨论】:

    标签: c# hash dictionary


    【解决方案1】:

    如果你有 resharper,你可以使用 Alt-Ins -> Equality 成员生成这些方法。

    这是为您生成的 KeyStruct 代码:

    public struct KeyStruct : IEquatable<KeyStruct>
    {
        public string Value1 { get; private set; }
        public long Value2 { get; private set; }
    
        public KeyStruct(string value1, long value2)
            : this()
        {
            Value1 = value1;
            Value2 = value2;
        }
    
        public bool Equals(KeyStruct other)
        {
            return Equals(other.Value1, Value1) && other.Value2 == Value2;
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != typeof (KeyStruct)) return false;
            return Equals((KeyStruct) obj);
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                return ((Value1 != null ? Value1.GetHashCode() : 0)*397) ^ Value2.GetHashCode();
            }
        }
    
        public static bool operator ==(KeyStruct left, KeyStruct right)
        {
            return left.Equals(right);
        }
    
        public static bool operator !=(KeyStruct left, KeyStruct right)
        {
            return !left.Equals(right);
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果 KeyStruct 是结构体(用 struct C# 关键字声明),不要忘记重写 Equals 和 GetHash 代码方法,或者为字典构造函数提供自定义的 IEqualityComparer,因为 ValueType.Equals 方法的默认实现使用反射来比较两者的内容结构实例。

      最好使 KeyStruct 不可变,如果这样做,您可以计算结构实例哈希一次,然后简单地从 GetHashCode 方法返回它。但这可能是过早的优化,取决于您需要多久按一次键获取值。

      一般情况下,使用结构体作为字典键即可。

      或者您可能在问如何实现 GetHashCode 方法?

      【讨论】:

      • 是的,这主要是关于我将如何实施高效的 GetHashCode() - 方法,不是在速度方面,而是在“数据选择”方面。我现在知道,我有两个字段,一个是字符串(可以为空,这是一个非常重要的要求,因为我正在与遗留系统交谈),另一个是长字段。
      • 简单地为结构提供哈希码作为结构数据哈希码的组合(如 sum 或 xor)。例如: public override int GetHashCode() { uncheked // 防止算术溢出 { return StringComparer.OrdinalIgnoreCase.GetHashCode(_myFirstField) + EqualityComparer.Default.GetHashCode(_myLongField); } }
      • 将其放入您的答案中可能是有意义的。
      【解决方案3】:

      您需要实现(覆盖)两种方法。
      1.bool Equals(object)
      2.int GetHashCode()

      哈希码不必是唯一的,但不同的对象返回相同的哈希码越少,您将获得更好的性能。

      你可以使用类似的东西:

      public int GetHashCode()
      {
          int strHash = str == null ? 0 : str.GetHashCode();
          return ((int)lng*397) ^  strHash;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-04-15
        • 2011-06-21
        • 2022-09-28
        • 2011-12-31
        • 2013-10-21
        • 2013-08-02
        • 1970-01-01
        • 2013-02-05
        • 1970-01-01
        相关资源
        最近更新 更多