简体   繁体   中英

C# abstract record with abstract Equals method

Why are we not allowed to do the following for a record

abstract record AA
{
  public abstract bool Equals(AA other);
}

record BB:AA
{
  public override bool Equals(AA other)// error as it is already implemented
  {
    //do some thing
  }
}

while it is totally acceptable for classes?

abstract class AA
{
   public abstract bool Equals(AA other);
}

class BB:AA
{
  public override bool Equals(AA other)
  {
    //do some thing
  }
}

By the way, I am doing this implementation to enforce the Equals check to cascade to its derived classes.

Edit: just to give context on why am I interested on this is because I am currently creating an library/autogenerator for IEquatable.

Edit/Info 2: Based on the comments, I have done some tests. since the abstract Equals method of record can't be overridden, I tried leaving it as is.

public abstract record AA
{
    public int Prop1 { get; set; }
    public string? Prop2 { get; set; }
    public string? Prop5 { get; set; }
    public abstract bool Equals(AA? other);
}

public record BB : AA
{
    public string? Prop3 { get; set; }
}

The result I get an error of System.BadImageFormatException: Bad IL format.

All in all, abstract Equals method on records is not just an unnecessary implementation but is also a bad one.

This is because compiler already implements equality methods for records. Check Value equality of records:

To implement value equality, the compiler synthesizes the following methods:

  • An override of Object.Equals(Object).

  • This method is used as the basis for the Object.Equals(Object, Object) static method when both parameters are non-null.

  • A virtual Equals method whose parameter is the record type. This method implements IEquatable.

  • An override of Object.GetHashCode().

  • Overrides of operators == and.=.

It means that there's not need to enforce the implementation of Equals method in the base abstract record.

If you still want to have custom Equals method implementation and derive from some base record you could do so by declaring virtual Equals method with the derived type as an argument:

abstract record AA
{
    // Redundant in case of records and can be omitted.
    public abstract bool Equals(AA other);
}

record BB : AA
{
    public virtual bool Equals(BB other)
    {
        throw new NotImplementedException();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM