首页 > 解决方案 > 带有抽象 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: Bad IL format。

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

标签: c#record

解决方案


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

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

  • Object.Equals(Object) 的覆盖。

  • 当两个参数都不为空时,此方法用作 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();
    }
}

推荐阅读