Linq & distinct implementing equals & gethashcode

therefore, I am trying to do this work, and I cannot understand why this is not working.

demo code;

namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var myVar = new List<parent >(); myVar.Add(new parent() { id = "id1", blah1 = "blah1", c1 = new child() { blah2 = "blah2", blah3 = "blah3" } }); myVar.Add(new parent() { id = "id1", blah1 = "blah1", c1 = new child() { blah2 = "blah2", blah3 = "blah3" } }); var test = myVar.Distinct(); Console.ReadKey(); } } public class parent : IEquatable<parent> { public String id { get;set;} public String blah1 { get; set; } public child c1 { get; set; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; // Suitable nullity checks etc, of course :) hash = hash * 23 + id.GetHashCode(); hash = hash * 23 + blah1.GetHashCode(); hash = hash * 23 + (c1 == null ? 0 : c1.GetHashCode()); return hash; } } public bool Equals(parent other) { return object.Equals(id, other.id) && object.Equals(blah1, other.blah1) && object.Equals(c1, other.c1); } } public class child : IEquatable<child> { public String blah2 { get; set; } public String blah3 { get; set; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; // Suitable nullity checks etc, of course :) hash = hash * 23 + blah2.GetHashCode(); hash = hash * 23 + blah3.GetHashCode(); return hash; } } public bool Equals(child other) { return object.Equals(blah2, other.blah2) && object.Equals(blah3, other.blah3); } } } 

can anyone spot my error (s)?

+7
source share
4 answers

You need to override the Equals(object) method:

 public override bool Equals(object obj) { return Equals(obj as parent); } 

The object.Equals method (unlike EqualityComparer<T>.Default ) does not use the IEquatable interface. Therefore, when you write object.Equals(c1, other.c1) , it does not call your Child.Equals(Child) method.

You do not have to do this for parent , but you really should.

+5
source

Either you do what SLaks offers, or use EqualityComparer<child>.Default in your parent class to use your IEquatable<child> implementation:

  public bool Equals(parent other) { return object.Equals(id, other.id) && object.Equals(blah1, other.blah1) && EqualityComparer<child>.Default.Equals(c1, other.c1); } 
+3
source

When adding a hash calculation, you can try something like

<code> hash ^ = id.GetHashCode (); Code>

Not sure if this is causing your problem.

0
source

There are a few things here. If I am going to implement any aspect of equality in a class such as GetHashCode , overriding == or IEquatable , I always use the following pattern.

  • Override Equals
  • Override GetHashCode
  • Implement IEquatable<T> , which means implementing Equals(T)
  • We realize! =
  • Implementation ==

So, if I had a class called ExpiryMonth with the Year and Month properties, here is what this implementation would look like. This is a pretty pointless task to adapt to other types of classes now.

I based this template on several other stackoverflow answers that are all trustworthy, but which I did not track along the way.

Always implementing all of these elements together, it provides the right equality operations in various contexts, including dictionaries and Linq operations.

  public static bool operator !=(ExpiryMonth em1, ExpiryMonth em2) { if (((object)em1) == null || ((object)em2) == null) { return !Object.Equals(em1, em2); } else { return !(em1.Equals(em2)); } } public static bool operator ==(ExpiryMonth em1, ExpiryMonth em2) { if (((object)em1) == null || ((object)em2) == null) { return Object.Equals(em1, em2); } else { return em1.Equals(em2); } } public bool Equals(ExpiryMonth other) { if (other == null) { return false; } return Year == other.Year && Month == other.Month; } public override bool Equals(object obj) { if (obj == null) { return false; } ExpiryMonth em = obj as ExpiryMonth; if (em == null) { return false; } else { return Equals(em); } } public override int GetHashCode() { unchecked // Overflow is not a problem { var result = 17; result = (result * 397) + Year.GetHashCode(); result = (result * 397) + Month.GetHashCode(); return result; } } 
0
source

All Articles