compare objects for equality - if the values of the properties are the same

2.9k Views Asked by At

I don't use is so often. So that is why I ask this question.

But apparently it is not possible in C# to just do a simple comparison with objects. So of course I googled first, but I only found very redundant solutions. And I know that you can can by javascript serialize the objects and then back to strings and then compare the properties with each other.

Because I just want to compare two simple objects - if the value of the properties are the same. So I have this:

public class Person
{

    public string FirstName { get; set; }
    public string LastName { get; set; }   


    public Person()
    {
    }

    public bool IsEqualTo(Person compareTo)
    {
        return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
    }

 public static bool AreEqual<AnyType>(AnyType mass1, AnyType mass2) where AnyType : IComparable<AnyType>
        {
            return mass1.CompareTo(mass2) == 0;
        }


    public Person(string lastName, string firstName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }  
}

But then I can't use the AreEqual method like this:

var person = new Person("Niels","Engelen");
var person99 = new Person("Niels", "Engelen")

 var equals = Person.AreEqual(person,  person99);

And so:

 var equals = person.CompareTo(person99);

This of course doesn't work.

So only this works then?

 public bool IsEqualTo(Person compareTo)
    {
        return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
    }

Than the output of:

   var equals = person.IsEqualTo(person99);

will be true.

But then you have to compare every property.

So is there no short method for comparing objects?

Thank you.

Very strange that in such a huge language like C# you don't have a method where you can compare Objects for equality.

I searched some more and I found that you do it with records:

var record1 = new Person.Hello("Niels", "Engelen");
var record2 = new Person.Hello("Niels", "Engelen");

var equalRecords = record1 == record2;
Console.WriteLine("Records " +  equalRecords);

Even in Javascript you can compare complex objects the easy way.

3

There are 3 best solutions below

2
SomeBody On BEST ANSWER

You can use reflection to loop over all properties of your class and compare them:

public bool IsEqualTo(Person other)
    {
        foreach(var prop in typeof(Person).GetProperties())
        {
            var value1 = prop.GetValue(this);
            var value2 = prop.GetValue(other);
            if(!value1.Equals(value2))
            {
                return false;
            }
        }
        return true;
    }

If you add or remove any properties, you won't have to modify your IsEqualTo method. The downside of this approach is that refelction has typically a low performance. If you do a lot of comparisions, this might not be a good solutions.

2
Sergey Borodin On

Implement interface IEquatable<T> and then you can use method Equals for Person.

 public class Person : IEquatable<Person>
   {

    public string FirstName { get; set; }
    public string LastName { get; set; }


    public Person()
    {
    }

    public bool Equals(Person compareTo)
    {
        return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(FirstName, LastName);
    }

    public Person(string lastName, string firstName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }
  }

  var person1 = new Person("test", "test");
  var person2 = new Person("test", "test");
  Assert.AreEqual(person1, person2);
  //true

Also your have to override method GetHashCode.

0
Zohar Peled On

Assuming you're working with c#9 or later, you can simply use declare your types as records and get that value-based compare from the compiler out of the box:

public record Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Note: Whether you're switching to records or not, you should consider making your types immutable whenever possible - so change {get;set;} to {get;init} or {get;} only properties.

If you're working with older versions of c#, you should consider implementing the IEquatable<T> interface.
Important:

If you implement IEquatable, you should also override the base class implementations of Equals(Object) and GetHashCode() so that their behavior is consistent with that of the Equals(T) method. If you do override Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. In addition, you should overload the op_Equality and op_Inequality operators. This ensures that all tests for equality return consistent results.