C# 确保在C中调用基方法#

C# 确保在C中调用基方法#,c#,inheritance,overriding,base,C#,Inheritance,Overriding,Base,我是否可以强制派生类始终调用重写的基方法 public class BaseClass { public virtual void Update() { if(condition) { throw new Exception("..."); // Prevent derived method to be called } } } 然后在派生类中: public override void Updat

我是否可以强制派生类始终调用重写的基方法

public class BaseClass
{
    public virtual void Update()
    {
        if(condition)
        {
            throw new Exception("..."); // Prevent derived method to be called
        }
    }
}
然后在派生类中:

public override void Update()
{
    base.Update(); // Forced call

    // Do any work
}
我搜索并找到了一个建议,建议使用非虚拟Update(),但也使用受保护的虚拟UpdateEx()。感觉不是很整洁,没有更好的方法吗


我希望你能理解我的问题,我为英语不好感到抱歉。

我认为你的建议很好


唯一一个基类方法,您无法避免从基类构造函数中的子类调用。

我认为拥有一个非虚拟的基类成员来调用一个可以扩展的虚拟“钩子”,这是此类问题最常见的解决方案

根据您的用例,您可能希望改用
事件
,但实现事件的通常模式是使用虚拟
OnEvent
方法,子类可以覆盖该方法,而不是添加事件处理程序,因此,在您的示例中,它归结为同一件事。

使用-don't override the base method(不重写需要做一些工作的基方法),重写一个特定的位,它可以是抽象的,也可以是基类中的no op。(关于是否将其变为无操作或抽象的决定通常是相当明显的——基类本身作为一个具体类是否有意义?)


听起来这基本上就是你在
UpdateEx
中发现的模式——尽管在我的经验中通常是
UpdateImpl
或类似的模式。在我看来,作为一种模式,这没有什么错——它避免了强迫所有派生类编写相同的代码来调用基方法的想法。

我花了一点时间才得到Update和UpdateEx的样子。下面是一个可能对其他人有所帮助的代码示例

public class BaseClass
{
    // This is the Update that class instances will use, it's never overridden by a subclass
    public void Update()
    {
        if(condition);
        // etc... base class code that will always run

        UpdateEx(); // ensure subclass Update() functionality is run
    }

    protected virtual void UpdateEx()
    {
        // does nothing unless sub-class overrides
    }
}
子类永远不会有Update()的任何实现。它将使用UpdateEx()向Update()添加实现


ConcreteClass的任何实例都将使用Update()的基类实现,但是ConcreteClass使用UpdateEx()扩展了它。

虽然我同意模板方法模式通常更可取,但应该注意的是BCL大量使用了“重写必须调用基类方法”(anti?)模式。Windows窗体类尤其如此。如果您有两个级别的层次结构,仍然希望在所有级别上强制执行基本调用,这是否意味着您将获得一个
UpdateImpl2
?@DirkBoer:您的意思是,如果所有“孙子”类最终都应调用三个方法?如果是这样的话,那么是的,类似的东西-但我会尽量简化设计。你可能是对的。也许一个OnCreate事件或者类似的事情更有意义。谢谢你的快速回答!这样,调用基方法和子方法的顺序很容易控制,这是另一个优点。
public class ConcreteClass : BaseClass
{
    protected override void UpdateEx()
    {
        // implementation to be added to the BaseClass Update();
    }
}