带有抽象Equals方法的C#抽象记录



为什么不允许我们对记录执行以下操作

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
}
}

而这对课堂来说是完全可以接受的?

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

顺便说一句,我这样做是为了强制执行Equals检查,以级联到它的派生类。

编辑:只是为了说明我为什么对此感兴趣,因为我目前正在为IEquatable创建一个库/自动生成器。

编辑/信息2:根据评论,我做了一些测试。由于不能重写记录的抽象Equals方法,我尝试保持原样。

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; }
}

结果我得到一个System.BadImageFormatException的错误:错误的IL格式

总而言之,记录上的抽象Equals方法不仅是一个不必要的实现,而且也是一个糟糕的实现。

这是因为编译器已经为记录实现了相等方法。检查记录的值相等性:

为了实现值相等,编译器综合了以下方法:

  • Object.Equals(Object(.的重写

  • 当两个参数都为非null时,此方法用作Object.Equals(Object,Object(静态方法的基础。

  • 一个虚拟Equals方法,其参数为记录类型。此方法实现IEquatable。

  • Object.GetHashCode((.的重写

  • 运算符==和!=的覆盖。

这意味着不需要在基本抽象记录中强制实现Equals方法。

如果您仍然希望实现自定义Equals方法并从某个基本记录派生,可以通过声明以派生类型为参数的虚拟Equals方法来实现:

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();
}
}

最新更新