Search code examples
c#.netlistobjectequality

Check if 2 objects contain the same data in fields


I have a Pharmacy class which contains lots of properties, and a Pharmacy is declared as unique by having the ID property as a key.

I have code in place which fetches all rows in a table from MySQL back to Pharmacy objects with their properties.

I want compare two List<Pharmacy> objects for the entries in them and check if the same ID exists in both tables, if it doesn't exist then add it to a new List<Pharmacy. If the ID exists in both but the data in the objects differs, then save that object to a new List<Pharmacy aswell.

This is how the class looks like.

public class Pharmacy
{
    [Key]
    public string Tunniste { get; set; }
    public string Lyhenne { get; set; }
    public string PitkaNimi { get; set; }
    public string YlempiYksikko { get; set; }
    public string Hierarkiataso { get; set; }
    public string VoimassaoloAlkaa { get; set; }
    public string VoimassaoloPaattyy { get; set; }
    ...
}

It's in Finnish but I hope you can live with that. Here's how I've tried to check if they're identical.

        for (int i = 0; i != pharmacyListFromArchive.Count; i++)
        {
            if (pharmacyListFromArchive[i].Equals(pharmacyListFromNew[i]))
            {
                Console.WriteLine("Objects are identical.");
            }
            else
            {
                Console.WriteLine("Objects are NOT identical. {0} - {1}", pharmacyListFromArchive[i].Tunniste, pharmacyListFromNew[i].Tunniste);
            }
        }

But when I run that, none of the objects register as identical even though they are identical in data. How can I work around this?


Solution

  • The standard implementation of Equals checks only for reference equality. What is the default behavior of Equals Method?

    You can either override the behavior of Equals. Guidelines for Overriding Equals() and Operator == (C# Programming Guide).

    public class Pharmacy  {
       // fields ...
    
       public override bool Equals(object obj) {
           // If parameter is null return false.
            if (obj == null) {
                return false;
            }
    
            // If parameter cannot be cast to Pharmacy return false.
            Pharmacy p = obj as Pharmacy;
            if ((System.Object)p == null) {
                return false;
            }
    
            // Return true if the fields match:
            return p.Lyhenne == this.Lyhenne &&
                   p.PitkaNimi == this.PitkaNimi
                   // && etc...
            ;
       }
    
        public override int GetHashCode() {
            return Lyhenne.GetHashCode() ^ PitkaNimi.GetHashCode() /* ^ etc ... */;
        }
    }
    

    Or you implement a custom IEqualityComparer IEqualityComparer Interface. This might be preferable if your ORM Mapper relies on the default equals (like Entity Framework does).