C# 如何使用重写 Equals() 的逻辑实现对 GetHashCode() 的重写

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9827911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 10:47:42  来源:igfitidea点击:

how to implement override of GetHashCode() with logic of overriden Equals()

c#overridinggethashcode

提问by rene

I have some classes as below, i have implemented the Equals(Object)method for almost all of them. But i don't know how to write GetHashCode(). As far I used these data types as value type in a DictionaryCollection, i think i should override GetHashCode().

我有一些如下类,我已经Equals(Object)为几乎所有的类实现了该方法。但是我不知道怎么写 GetHashCode()。就我使用这些数据类型作为Dictionary集合中的值类型而言,我认为我应该覆盖GetHashCode().

1.I don't know how to implement GetHashCode()with logic of Equals(Object).

1.我不知道如何GetHashCode()Equals(Object).

2.There are some derived classes, if i override GetHashCode()and Equals(Object)for base class ( Param), is it still necessary to override it for childs?

2.有一些派生类,如果我重写GetHashCode()Equals(Object)为基类(Param),它仍然需要覆盖它用于儿童的?

class Param
{
    ...
    public Int16 id { get; set; }
    public String name { get; set; }
    ...
    public override bool  Equals(object obj)
    {
        if ( obj is Param){
            Param p = (Param)(obj);
            if (id > 0 && p.id > 0)
                return (id == p.id);
            else if (name != String.Empty && p.name != String.Empty)
                return (name.equals(p.name));
            else
                return object.ReferenceEquals(this, obj);
        }
        return false;
    }
}  
class Item
{
    public int it_code { get; set; }
    public Dictionary<String, Param> paramAr { get; set; }
    ...
    public override bool Equals(Object obj)
    {
        Item im = new Item();
        if (obj is Item)
            im = (Item)obj;
        else 
            return false;

        if (this.it_code != String.Empty && im.it_code != String.Empty)
            if (this.it_code.Equals(im.it_code)) 
                return true;

        bool reParams = true;
        foreach ( KeyValuePair<String,Param> kvp in paramAr ){
            if (kvp.Value != im.paramAr[kvp.Key]) {
                reParams = false;
                break;
            }
        }
        return reParams;
    }
}
class Order
{

    public String or_code { get; set; }
    public List <Item> items { get; set; }
    ...
    public override bool Equals( Object obj ){
        Order o = new Order();
        if (obj is Order)
            o = (Order)obj;
        else
            return false;

        if (this.or_code != String.Empty && o.or_code != String.Empty)
            if (this.or_code.Equals(o.or_code))
                return true;
        bool flag = true;
        foreach( Item i in  items){
            if (!o.items.Contains(i)) { 
                flag = false;
                break;
            }
        }
        return flag;
    }
}

EDIT:i get this warning:

编辑:我收到此警告:

Warning : 'Item' overrides Object.Equals(object o) but does not override Object.GetHashCode()

警告:'Item' 覆盖 Object.Equals(object o) 但不覆盖 Object.GetHashCode()

采纳答案by kaj

Firstly, as I think you understand, wherever you implement Equalsyou MUST also implement GetHashCode. The implementation of GetHashCodemust reflect the behaviour of the Equalsimplementation but it doesn't usually useit.

首先,正如我认为您所理解的,无论您在何处实施,Equals都必须实施GetHashCode. 的实现GetHashCode必须反映实现的行为,Equals但它通常不使用它。

See http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx- especially the "Notes to Implementers"

请参阅http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx- 特别是“实施者注意事项”

So if you take your example of the Itemimplementation of Equals, you're considering both the values of idand nameto affect equality. So both of these must contribute to the GetHashCodeimplementation.

因此,如果您以 的Item实现为例Equals,您将同时考虑idname影响平等的价值。因此,这两者都必须有助于GetHashCode实施。

An example of how you could implement GetHashCodefor Itemwould be along the lines of the following (note you may need to make it resilient to a nullable namefield):

您可以如何实现GetHashCodefor的示例Item如下(请注意,您可能需要使其适应可空name字段):

public override GetHashCode()
{
    return id.GetHashCode() ^ name.GetHashCode();
}

See Eric Lippert's blog post on guidelines for GetHashCode- http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

请参阅 Eric Lippert 关于指南的博客文章GetHashCode- http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

As for whether you need to re-implement GetHashCodein subclasses - Yes if you also override Equals- as per the first (and main) point - the implementation of the two must be consistent - if two items are considered equal by Equalsthen they must return the same value from GetHashCode.

至于您是否需要GetHashCode在子类中重新实现- 是的,如果您还覆盖Equals- 根据第一个(和主要)点 - 两者的实现必须一致 - 如果两个项目被认为是相等的,Equals那么它们必须返回相同值来自GetHashCode.

Side note: As a performance improvement on your code (avoid multiple casts):

旁注:作为代码的性能改进(避免多次转换):

if ( obj is Param){
    Param p = (Param)(obj);

Param p = obj as Param;
if (p != null) ...

回答by Alex

I prefer Josh Bloch's aproach.

我更喜欢 Josh Bloch 的方法。

Here's the example for the Paramclass.

这是Param该类的示例。

override GetHashCode(object obj)
{
 unchecked
    {
        int hash = 17;

        hash = hash * 23 + id.GetHashCode();
        hash = hash * 23 + name.GetHashCode();
        return hash;
    }
}

Also, check this link out : .net - best algorithm for GetHashCodeProperties used for the hashcode computation should be immutable as well.

此外,请查看此链接:.net -用于哈希码计算的GetHashCode属性的最佳算法也应该是不可变的。