【问题标题】:C# abstract record with abstract Equals method带有抽象 Equals 方法的 C# 抽象记录
【发布时间】:2021-05-03 08:58:11
【问题描述】:

为什么不允许我们做以下记录

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 创建一个library/autogenerator

Edit/Info 2:基于cmets,我做了一些测试。由于无法覆盖抽象的 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


    【解决方案1】:

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

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

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

    【讨论】:

    • 您链接到的页面还显示“如果记录类型具有与任何合成方法的签名匹配的方法,则编译器不会合成该方法”,其中意味着,在这种特殊情况下,编译器应该合成这样的方法。
    • 在继承的情况下,public bool Equals(AA other) 会在基本记录中生成,这会导致错误。不过,在派生记录中创建 public virtual bool Equals(BB other) 是有效的。
    • 总而言之,public abstract bool Equals(AA other); 不仅是一个不必要的记录实现,而且是一个糟糕的实现。
    • @MKtsisD 我无法在我的测试中证明在我测试的任何场景中添加抽象 Equals 到抽象记录会改变行为。它可能会产生误导,是的,但并不是真正有害的。如果两种不同的派生类型导致比较一个记录和 null 由于基础转换,我还建议不要使用记录的基本记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 2011-06-03
    相关资源
    最近更新 更多