Roslyn: Synthesized record Equals() should compare fields from non-record base class

Created on 5 Jun 2020  路  5Comments  路  Source: dotnet/roslyn

The following prints True rather than False because the synthesized bool Equals(B other) method does not compare inherited fields from the non-record base type.
```C#
class A
{
internal A(int X) { this.X = X; }
internal int X { get; set; }
}

record B(int X, int Y) : A(X)
{
}

class Program
{
static void Main()
{
System.Console.WriteLine(new B(0, 2).Equals(new B(1, 2)));
}
}
```

Area-Compilers New Language Feature - Records

Most helpful comment

IMO a record that inherits from a non-record shouldn't make assumptions regarding how equality should be calculated for the base class. I suggest calling base.Equals and base.GetHashCode, unless those methods are not overridden by any type in the hierarchy and would result in a call to object.Equals or object.GetHashCode, in which case the compiler could elide the base call. This is how Scala handles equality with case classes that inherit from non-case classes and it works pretty well.

All 5 comments

IMO a record that inherits from a non-record shouldn't make assumptions regarding how equality should be calculated for the base class. I suggest calling base.Equals and base.GetHashCode, unless those methods are not overridden by any type in the hierarchy and would result in a call to object.Equals or object.GetHashCode, in which case the compiler could elide the base call. This is how Scala handles equality with case classes that inherit from non-case classes and it works pretty well.

Records can only inherit from other records or System.Object.

This can be re-opened and semantics explored if we decide to lift that restriction

@agocke @cston

Out of curiosity, how will the compiler recognize that the base type is a "record"?

At the moment, because the design happens to generate a clone method called <>Clone, we use its presence to indicate a record.

Was this page helpful?
0 / 5 - 0 ratings