Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advantage of deriving external class from IEqualityComparer<> over overriding GetHashCode and Equals

I'm need to hash against a member variable instead of the class, so I don't check if the reference is in the dictionary. Without overriding the defaults, it won't find an identical Value, but only return if it finds the same exact instance of HashedType, such that this code fails.

Dictionary.Add(new HashedType(4));
Dictionary.Contains(new HashedType(4)); // fails to find 4

Definition of HashedType:

HashedType
{
   public HashedType(Int32 value) { Value = value); }
   public HashedType(String value) { Value = value); }
   public object Value;
   public void Serialize(Serializer s)
   {
      if (Value.GetType() == typeof(Int32)) 
      {
         s.Set<Int32>(0);
         s.Set<Int32>(Value);
      }
      else 
      {
         s.Set<Int32>(1);
         s.Set<String>(Value);
      }

   }
}

It looks like I can override GetHashCode() and Equals() to do this for me.

However, MSDN recommends I create a separate class that I derive from IEqualityComparer and instantiate my dictionaries used HashedType with the HashedTypeComparer : IEqualityComparer.

To help make this easier, I've derived from Dictionary and created

HashedTypeDictionary<U> : Dictionary<T,U> 
{ 
   public HashedTypeDictionary() : base(new  HashedTypeComparer()) { } 
   public bool Equals(HashedType a, HashedType b) { return a.Value == b.Value; }
   publci int GetHashCode(HashedType a) { return a.Value.GetHashCode(); } 
}

This all seems contrived.

Is the only advantage I get is not changing the Equals()?

I mean, really speaking, I would want Equals to compare against that single member anyway.

like image 202
Lee Louviere Avatar asked Feb 22 '12 18:02

Lee Louviere


People also ask

What happens if we only override equals method in Java?

If we only override equals (Object) method, when we call map.put (g1, “CSE”); it will hash to some bucket location and when we call map.put (g2, “IT”); it will hash to some other bucket location because of different hashcode value as hashCode () method has not been overridden.

Why should I override hashCode when I override equals?

The reason why you should override hashcode whenever you override equals is that you need a way to create the same object you want to find. This is particularly useful when you are dealing with collections.

How to implement gethashcode and equals in Java?

The simplest way to implement GetHashCode () is to use the built-in System.HashCode.Combine () method and pick the properties you want to include. Let it do the work for you. Furthermore, the simplest way to implement Equals () is to use the is operator and compare all the properties.

How to check if two objects are equal in Java?

If two objects are equal according to the equals (Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.


3 Answers

The idea is that object.Equals is the natural equality for that type (and GetHashCode should match that idea of equality). IEqualityComparer is used when you want a different equality on a case-by-case basis.

Consider for example, a string. The overridden Equals & GetHashCode methods do case-sensitive comparisons. But what if you want a dictionary where the keys are not case-sensitive? You write an IEqualityComparer that is not case-sensitive and pass it in the constructor of the dictionary.

Your examples sounds like any two instances of HashedType are to be normally treated as equal if their members are equal. In that case I'd recommend overriding the object.Equals and object.GetHashCode methods and not writing a IEqualityComparer.

like image 98
R. Martinho Fernandes Avatar answered Oct 12 '22 13:10

R. Martinho Fernandes


The reason you would choose one over the other is whether you always want instances of a given type to be compared using a certain logic, or only in this one situation.

Equals and GetHashCode provide the "true" implementation of whether two objects are logically equal. IEqualityComparer allows you to override that in a case-by-case basis, and to separate ownership (it might be different parties who control the entities versus the code using them).

like image 24
Rex M Avatar answered Oct 12 '22 12:10

Rex M


Imagine, for a moment, that you don't own the underlying class (i.e. it's produced by another team, or only given to you as a binary). You always can create the IEqualityComparer. You might not have the option of changing Equals and GetHashCode...

like image 45
Damien_The_Unbeliever Avatar answered Oct 12 '22 13:10

Damien_The_Unbeliever