C# 属性或代码检查注释以鼓励或阻止从虚拟方法覆盖调用基方法

C# Attribute or Code Inspection Comment to Encourage or Discourage Call to Base Method from Virtual Method Override

我正在使用 Rider 在 Unity 中开发一个 C# 项目。

我有时会看到一个带有空虚方法的基础 class,然后是一个覆盖该方法的派生 class。即使基本方法为空,方法覆盖也会显式调用 base.MethodName()

public class A
{
    public virtual void Method1() { }

    public virtual void Method2()
    {
        // Important logic performed here!
    }
}

public class B : A
{
    public override void Method1()
    {
        base.Method();

        // Do something else ...
    }

    public override void Method2()
    {
        // Do something here ...
    }
}

在 Rider 的 IL 查看器中查看方法时,包括对基本方法的调用,即使该方法是空的。

C# 或 Rider 中是否有任何方法属性或代码检查注释可以:

  1. 调用空基方法时生成编译器或代码检查警告。

  2. not 调用 not 为空的基方法时生成编译器或代码检查警告。

例如:

public class A
{
    [OmitCallFromOverride]
    public virtual void Method1() { }

    [RequireCallFromOverride]
    public virtual void Method2()
    {
        // Important logic performed here!
    }
}

我可以想象这样一种情况:多个派生 classes 重写一个方法,一个或多个错误地调用基方法失败,这可能会导致意外行为。或者对空基方法进行不必要调用的情况,这可能是浪费,但不太可能破坏任何东西。

虽然我主要是询问是否存在此类属性或代码检查注释,但我也很想知道人们如何处理这些情况,例如总是从重写中调用基本方法,保持重要逻辑脱离基本虚方法,或使用其他一些方法来表明基本方法调用是不必要的还是必需的。

Generate a compiler or code inspection warning when calling a base method that is empty.

据我所知,在c#中,没有针对空方法的警告。因此,我认为 调用空的基本方法时没有警告
不过有空给你写一个:Write your first analyzer and code fix

Generate a compiler or code inspection warning when not calling a base method that is not empty.

不在 C# 中,我认为强制派生 class 调用基方法不是一个好主意。我可以理解,在您的场景中,如果您的所有派生 classes 方法始终调用基本方法,那就太好了,但这种情况非常少见。而且通常当我们需要棘手的(不直观的)规则时,这意味着我们的解决方案不是很清楚,或者会是 error-prone.

keeping important logic out of base virtual methods

如果您需要 A.Method1 被调用,也许让它作为 virtual 方法不是一个好主意。当您想为派生的 classes 提供使用它的机会或用更适合的版本覆盖它时,您有一个 virtual 方法。
我建议你一个解决方案,也许你可以适应你的场景。

abstract class A
{        
    public abstract void Method1();

    public virtual void Method2() { }

    public void MustBeCalled() 
    { 
        // Here you can put the logic you had in Method1, you need to execute this code, so this method can't be overwrited.             
    }

    public void TemplateMethod()
    {
        Method1();
        MustBeCalled();
        // Do something else ...
    }

}