Comparing two collections of same object in C# and Finding New, Changed or Deleted Records

379 views Asked by At

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?

2

There are 2 answers

1
2bis On

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

0
Jamiec On

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.