Home > Back-end >  How should I implement equality checking for classes that have objects of other classes as member?
How should I implement equality checking for classes that have objects of other classes as member?

Time:07-11

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?

CodePudding user response:

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.

CodePudding user response:

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)

  • Related