简体   繁体   English

我为什么不*覆盖GetHashCode()?

[英]Why should I *not* override GetHashCode()?

My search for a helper to correctly combine constituent hashcodes for GetHashCode() seemed to garner some hostility. 搜索帮助器正确组合GetHashCode()成分哈希码似乎带来了一些敌意。 I got the impression from the comments that some C# developers don't think you should override GetHashCode() often - certainly some commenters seemed to think that a library for helping get the behaviour right would be useless. 我从评论中得到的印象是,一些C#开发人员认为你不应该经常覆盖GetHashCode() - 当然一些评论者似乎认为用于帮助正确行为的库将毫无用处。 Such functionality was considered useful enough in Java for the Java community to ask for it to be added to the JDK , and it's now in JDK 7 . 这种功能在Java中被认为是有用的,Java 社区要求将它添加到JDK中现在已经在JDK 7中了

Is there some fundamental reason that in C# you don't need to - or should definitely not - override GetHashCode() (and correspondingly, Equals() ) as often as in Java? 是否有一些基本原因在C#中你不需要 - 或者绝对不应该 - 像Java一样频繁地覆盖GetHashCode() (相应地, Equals() )? I find myself doing this often with Java, for example whenever I create a type that I know I want to keep in a HashSet or use as a key in a HashMap (equivalently, .net Dictionary ). 我发现自己经常使用Java,例如,每当我创建一个我知道要保留在HashSet或者用作HashMap的键(等效地,.net Dictionary )时。

C# has built-in value types which provide value equality, whereas Java does not. C#具有提供值相等的内置值类型,而Java则没有。 So writing your own hashcode in Java may be a necessity, whereas doing it in C# may be a premature optimisation. 因此,在Java中编写自己的哈希码可能是必要的,而在C#中执行它可能是一个不成熟的优化。

It's common to write a type to use as a composite key to use in a Dictionary/HashMap. 编写一个类型以用作在Dictionary / HashMap中使用的复合键是很常见的。 Often on such types you need value equality (equivalence) as opposed to reference equality(identity) , for example: 通常在这些类型上,您需要值相等(等价)而不是引用相等(标识) ,例如:

IDictionary<Person, IList<Movie> > moviesByActor; // e.g. initialised from DB
// elsewhere...
Person p = new Person("Chuck", "Norris");
IList<Movie> chuckNorrisMovies = moviesByActor[p];

Here, if I need to create a new instance of Person to do the lookup, I need Person to implement value equality otherwise it won't match existing entries in the Dictionary as they have a different identity. 在这里,如果我需要创建一个Person的新实例来进行查找,我需要Person来实现值相等,否则它将不匹配Dictionary中的现有条目,因为它们具有不同的标识。

To get value equality, you need an overridden Equals() and GetHashCode() , in both languages. 要获得值相等,您需要在两种语言中重写Equals()GetHashCode()

C#'s structs (value types) implement value equality for you (albeit a potentially inefficient one), and provide a consistent implementation of GetHashCode . C#的结构(值类型)为您实现值相等 (尽管可能是低效的),并提供GetHashCode的一致实现。 This may suffice for many people's needs and they won't go further to implement their own improved version unless performance problems dictate otherwise. 这可能足以满足许多人的需求,除非性能问题另有规定,否则他们不会进一步实施自己的改进版本。

Java has no such built-in language feature. Java没有这种内置语言功能。 If you want to create a type with value equality semantics to use as a composite key, you must implement equals() and correspondingly hashCode() yourself. 如果要创建具有值相等语义的类型以用作复合键,则必须自己实现equals()和相应的hashCode()。 (There are third-party helpers and libraries to help you do this, but nothing built into the language itself). (有第三方帮助程序和库可以帮助您完成此任务,但语言本身并未构建任何内容)。

I've described C# value types as 'potentially inefficient' for use in a Dictionary because: 我已经将C#值类型描述为在“词典”中使用“潜在低效”,因为:

If your object represents a value or type, then you SHOULD override the GetHashCode() along with Equals. 如果您的对象表示值或类型,那么您应该覆盖GetHashCode()和Equals。 I never override hash codes for control classes, like "App". 我从不覆盖控件类的哈希码,比如“App”。 Though I see no reason why even overriding GetHashCode() in those circumstances would be a problem as they will never be put in a position to interfere with collection indexing or comparisons. 虽然我认为在这些情况下甚至覆盖GetHashCode()是没有理由的,因为它们永远不会被置于干扰收集索引或比较的位置。

Example: 例:

public class ePoint : eViewModel, IEquatable<ePoint>
{
    public double X;

    public double Y;

    // Methods

    #region IEquatable Overrides

    public override bool Equals(object obj)
    {
        if (Object.ReferenceEquals(obj, null)) { return false; }

        if (Object.ReferenceEquals(this, obj)) { return true; }

        if (!(obj is ePoint)) { return false; }

        return Equals((ePoint)obj);
    }

    public bool Equals(ePoint other)
    {
        return X == other.X && Y == other.Y;
    }

    public override int GetHashCode()
    {
        return (int)Math.Pow(X,Y);
    }

    #endregion

我编写了一个帮助器类 ,使用属性数组中的值语义来实现GetHashCode()Equals()CompareTo()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NHibernate设置:我应该重写Equals和GetHashCode吗? - NHibernate set : Should I override Equals and GetHashCode? 如何为HashSet覆盖Equals和GetHashCode? - How should I override Equals and GetHashCode for HashSet? 为什么我不应该使用反射来实现 Equals 和 GetHashCode? - Why should I not implement Equals and GetHashCode using reflection? 为什么KeyValuePair不会覆盖Equals()和GetHashCode()? - Why does KeyValuePair not override Equals() and GetHashCode()? 我需要在引用类型上覆盖 GetHashCode() 吗? - Do I need to override GetHashCode() on reference types? 如何在常规BaseClass中重写GetHashCode - How do I override GetHashCode in a general BaseClass 在个人类上使用字典时,为什么不必覆盖GetHashCode? - Why don't I ever have to override GetHashCode when using Dictionaries on personal classes? 为什么我不能在EF4中的多对多实体上覆盖GetHashCode? - Why can't I override GetHashCode on a many-to-many entity in EF4? 为什么我收到此Resharper警告-不覆盖&#39;Object.Equals(object o)和&#39;Object.GetHashcode()&#39; - Why I am getting this Resharper warning - does not override 'Object.Equals(object o) and 'Object.GetHashcode()' 是否有一个示例为什么应该在NHibernate中覆盖Equals / GetHashCode? - Is there a sample why Equals/GetHashCode should be overwritten in NHibernate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM