bacar
bacar

Reputation: 10091

Why should I *not* override GetHashCode()?

My search for a helper to correctly combine constituent hashcodes for GetHashCode() seemed to garner some hostility. 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. 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.

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? 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).

Upvotes: 10

Views: 611

Answers (3)

bacar
bacar

Reputation: 10091

C# has built-in value types which provide value equality, whereas Java does not. So writing your own hashcode in Java may be a necessity, whereas doing it in C# may be a premature optimisation.

It's common to write a type to use as a composite key to use in a 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.

To get value equality, you need an overridden Equals() and GetHashCode(), in both languages.

C#'s structs (value types) implement value equality for you (albeit a potentially inefficient one), and provide a consistent implementation of 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. 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. (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:

Upvotes: 1

SLaks
SLaks

Reputation: 887195

I wrote a helper class to implement GetHashCode(), Equals(), and CompareTo() using value semantics from an array of properties.

Upvotes: 0

KindaFearless
KindaFearless

Reputation: 11

If your object represents a value or type, then you SHOULD override the GetHashCode() along with Equals. I never override hash codes for control classes, like "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.

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

Upvotes: 0

Related Questions