0

I have got two collections of same object

 public class MyClass
 { 
  public int Id {get;set;}
  public string Name {get;set;}
  public int Age{get;set;}
  public string SSN{get;set;}
}

I have got two Collections (colA and colB) based on MyClass and want to compare them in a way to find New, Changed or Deleted Records. My starting point was

  var diff = colA.Except(colB);

But this gives me wrong results and actually returning whole of colA

Then I made following changes in MyClass

 public Class MyClass
 {
 
    // Properties 
    public int Id {get;set;}
    public string Name {get;set;}
    public int Age{get;set;}
    public string SSN{get;set;}
  
  // Added override versions of following 
  
   public override int GetHashCode()
   {

       unchecked
       {
          return
            this.Id.GetHashCode();

       }
   }
   public override bool Equals(object obj)
   {
    var data = obj as MyClass;

      if (   (this.Id??0).Equals(data.Id ?? 0) 
          && (this.Age??0).Equals(data.Age ?? 0) 
          && (this.Name??string.Empty).Equals(data.Name ?? string.Empty)
          && (this.SSN??string.Empty).Equals(data.SSN ?? string.Empty) 
          )
                return true;

            return false;
   }
  
 }

To avoid failure on NULL I have applied NULL coalescing through ?? on different fields.

My Question is, Is this the best way of doing this or there can be a better way? and also how can this be changed to get what's been changed on field level?

  • this.Id can't be null because it's a value type. Same for this.Age. Also, data.Id can't be null, but data?.Id can. – Zohar Peled Jul 01 '20 at 10:00
  • Do you need their "relative position" in the collections? Meaning, are you looking to do something like what source control does? Or should *moved* items that are otherwise identical be ignored? In other words, will `Except` do what you want, or would you like to know *where* something was added or deleted? – Lasse V. Karlsen Jul 01 '20 at 10:16
  • Also, "changed", how will you know that? Is that objects that have the same Id, but other fields are different? Or can Id be different as well? – Lasse V. Karlsen Jul 01 '20 at 10:17

2 Answers2

1

The way I would approach this is as follows:

  • Implement a Diff method which, similar to Equals returns the list of fields which differ between the current and passed in instance
  • Use that method in Equals to check for equality. I might be tempted to implement IEquatable<MyClass> for a bit of type safety, and because it makes the code a little clearer
  • Use Except to check for new/deleted records as you have
  • Use Linq and my Diff method to pull out which records exist in both but with changes - you'll need to pick your "key" which I assume would be Id.
Jamiec
  • 133,658
  • 13
  • 134
  • 193
0

as far as i know best practice will be using the same equality members in both GetHashCode() and Equals(object obj).

if using resharper you can get help with this manual : https://www.jetbrains.com/help/resharper/Code_Generation__Equality_Members.html

2bis
  • 55
  • 11
  • 1
    The rule is this: HashCode for equal objects must be equal, however, equal hashCode doesn't necessarily means equal objects. This means that it is Ok to base the hash code calculation on partial equality (though not necessarily recommended). – Zohar Peled Jul 01 '20 at 09:51