How should I implement equality checking for classes that have objects of other classes as member?

81 Views Asked by At

I have a Student class that has an object of class Name.

At this point, the equality check of the Student class returns false, and I don't know why.

public class Student : IEquatable<Student>
{
  public Name Name { get; }

  public Student(Name name) => Name = name;

  public bool Equals(Student other)
  {
    if (ReferenceEquals(this, other))
      return true;
    if (ReferenceEquals(other, null))
      return false;

    return Name == (other.Name);
  }
}

public class Name : IEquatable<Name>
{
  public string First { get; }

  public Name(string first) => First = first;

  public bool Equals(Name other)
  {
    if (ReferenceEquals(this, other))
      return true;
    if (ReferenceEquals(other, null))
      return false;

    return First == other.First;
  }
}
var s1 = new Student(new Name("A"));
var s2 = new Student(new Name("A"));

Console.WriteLine(s1.Equals(s2).ToString());

Of course, doing the equality check this way will return true.

var s1 = new Student(new Name("A"));
var s2 = s1;

Console.WriteLine(s1.Equals(s2).ToString());

Can you tell me what I'm doing wrong?

2

There are 2 best solutions below

0
Yong Shun On BEST ANSWER

Solution 1 (Recommended)

Since you had implemented IEquatable interface for Name class, just calls .Equals() in Student class.

public class Student : IEquatable<Student>
{
    public Name Name { get; }

    public Student(Name name) => Name = name;
    public bool Equals(Student other)
    {
        if (ReferenceEquals(this, other))
            return true;
        if (ReferenceEquals(other, null))
            return false;
        return Name.Equals(other.Name); // Replaces with .Equals
    }
}

Sample .NET Fiddle (Solution 1)


Solution 2

Or you need to implement operator overloading for the == and != operators.

If you use == operator in:

public class Student : IEquatable<Student>
{
    ...

    public bool Equals(Student other)
    {
        ...

        return Name == (other.Name);
    }
}
public class Name : IEquatable<Name>
{
    ...
    
    public static bool operator == (Name a, Name b)
    {
        return a.First == b.First;
    }
    
    public static bool operator != (Name a, Name b)
    {
        return a.First != b.First;
    }
}

Sample .NET Fiddle (Solution 2)

0
Etienne de Martel On

So, == by default for reference types just compares references. Implementing IEquatable<T> does not overload == automatically, you have to do it yourself. string does overload that operator, so it works in Name, but your Name class doesn't, so in Student, the default behaviour is used, which is equivalent to ReferenceEquals().

Implementing IEquatable<T> correctly also means you need to override Equals(object) and GetHashCode(), which you don't do here.