当前位置:  开发笔记 > 编程语言 > 正文

使用对象的字段作为通用的Dictionary键

如何解决《使用对象的字段作为通用的Dictionary键》经验,为你挑选了3个好方法。

如果我想使用对象作为a的键Dictionary,我需要覆盖哪些方法以使它们以特定方式进行比较?

假设我有一个具有属性的类:

class Foo {
    public string Name { get; set; }
    public int FooID { get; set; }

    // elided
} 

我想创建一个:

Dictionary>

我希望Foo具有相同对象的对象FooID被视为同一组.我需要在Foo课程中覆盖哪些方法?

总结一下:我想将Stuff对象分类为按Foo对象分组的列表.Stuff对象将有一个FooID将它们链接到他们的类别.



1> Marc Gravell..:

默认情况下,两个重要的方法是GetHashCode()Equals().重要的是,如果两个东西相等(Equals()返回true),它们具有相同的哈希码.例如,您可能"返回FooID;" 因为GetHashCode(),如果你想,随着比赛.您也可以实现IEquatable,但这是可选的:

class Foo : IEquatable {
    public string Name { get; set;}
    public int FooID {get; set;}

    public override int GetHashCode() {
        return FooID;
    }
    public override bool Equals(object obj) {
        return Equals(obj as Foo);
    }
    public bool Equals(Foo obj) {
        return obj != null && obj.FooID == this.FooID;
    }
}

最后,另一种选择是提供IEqualityComparer相同的功能.


@Ken - 嗯,它只需要返回一个提供必要功能的int.哪个FooID和FooID.GetHashCode()一样好.作为实现细节,Int32.GetHashCode()是"return this;".对于其他类型(字符串等),则是:.GetHashCode()将非常有用.
+1并不意味着劫持这个帖子,但我的印象是GetHashCode()应该返回FooId.GetHashCode().这不是正确的模式吗?
谢谢!我选择了IEqualityComparer ,因为只有Dicarionary才需要覆盖方法.
@JørgenFogh我非常清楚这一点; 提供的示例与声明的意图一致.有很多与哈希不变性有关的相关问题; ID变化的次数少于名称,并且*通常*可靠唯一且等价的指标.但是,这是一个非平凡的主题.

2> Guffa..:

如您所希望的那样FooID是组的标识符,您应该将其用作字典中的键而不是Foo对象:

Dictionary>

如果您将Foo对象用作键,则只需实现GetHashCodeEquals方法以仅考虑该FooID属性.NameDictionary所涉及的而言,该属性只是自重,所以你只需要Foo用作一个包装器int.

因此,最好FooID直接使用该值,然后您不必像Dictionary使用int键作为已支持的那样实现任何内容.

编辑:
如果你想将Foo类作为键使用,IEqualityComparer很容易实现:

public class FooEqualityComparer : IEqualityComparer {
   public int GetHashCode(Foo foo) { return foo.FooID.GetHashCode(); }
   public bool Equals(Foo foo1, Foo foo2) { return foo1.FooID == foo2.FooID; }
}

用法:

Dictionary> dict = new Dictionary>(new FooEqualityComparer());



3> froh42..:

对于Foo,您需要覆盖object.GetHashCode()和object.Equals()

字典将调用GetHashCode()来计算每个值的哈希桶,并使用Equals来比较两个Foo是否相同.

确保计算好的哈希码(避免许多具有相同哈希码的相等Foo对象),但要确保两个等于Foos具有相同的哈希码.您可能希望从Equals-Method开始,然后(在GetHashCode()中)xor在Equals中比较的每个成员的哈希码.

public class Foo { 
     public string A;
     public string B;

     override bool Equals(object other) {
          var otherFoo = other as Foo;
          if (otherFoo == null)
             return false;
          return A==otherFoo.A && B ==otherFoo.B;
     }

     override int GetHashCode() {
          return 17 * A.GetHashCode() + B.GetHashCode();
     }
}


除了 - 但是xor(^)为哈希码做了一个糟糕的组合,因为它经常导致很多对角线碰撞(即{"foo","bar"} vs {"bar","foo"}.更好选择是乘以并添加每个项 - 即17*a.GetHashCode()+ B.GetHashCode();
马克,我明白你的意思了.但是你怎么得到神奇的数字17?使用素数作为乘法器来组合哈希值是否有利?如果是这样,为什么?
推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有