Do Record types' == operator perform equivalent comparisons to the 'Equals' method in classes implementing IEquatable<T>?

95 Views Asked by At

I have a class named 'Clock' that implements the IEquatable interface. I've implemented the 'Equals' method in my class to compare two objects like this:

public bool Equals(Clock? other)
{
    return _hours == other?._hours && _minutes == other._minutes;
}

When I changed my class to a record type and replaced the Equals method with the == operator, the results remained the same. Can I conclude that the Equals method in my class essentially performs the same comparison as the == operator does for record types?

Scenario one: I have two objects of Clock class like this and want to check value equality of two objects using Equals method which I added to my class.

Clock clock1 = new(2, 10);
Clock clock2 = new(2, 10);
if (clock2.Equals(clock1))
{
    Console.WriteLine("Equal");
}

Second scenario: changing my class to record type and comparing two objects with == operator

Clock clock1 = new(2, 10);
Clock clock2 = new(2, 10);
if (clock1 == clock2)
{
   Console.WriteLine("Equal");
}

In the both cases they return true. I wonder does Equals method does exact same thing as == ?

1

There are 1 best solutions below

0
Sweeper On BEST ANSWER

Yes, with a few basic assumptions, == for a record is the same as the Equals you wrote. From the proposal for records,

The synthesized Equals(R?) returns true if and only if each of the following are true:

  • other is not null, and
  • For each instance field fieldN in the record type that is not inherited, the value of System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN) where TN is the field type, and
  • If there is a base record type, the value of base.Equals(other) (a non-virtual call to public virtual bool Equals(Base? other)); otherwise the value of EqualityContract == other.EqualityContract.

The record type includes synthesized == and != operators equivalent to operators declared as follows:

public static bool operator==(R? left, R? right)
    => (object)left == right || (left?.Equals(right) ?? false);
public static bool operator!=(R? left, R? right)
    => !(left == right);

The Equals method called by the == operator is the Equals(R? other) method specified above.

Your Clock.Equals satisfy the conditions for the synthesised Equals to return true if we assume a few basic things, such as:

  • _hours and _minutes are the only fields of Clock
  • the types of _hours and _minutes are ints, or anything such that the default equality comparer for that type returns the same thing as comparing them with ==.
  • Clock doesn't have derived records (EqualityContract will always be equal)