Подтвердить что ты не робот

Убедитесь, что базовый метод вызывается в С#

Можно ли каким-то образом заставить производный класс всегда вызывать переопределенную базу методов?

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
}

Я искал и нашел предложение использовать не виртуальное обновление(), а также защищенный виртуальный UpdateEx(). Это просто не очень удобно, нет ли лучшего способа?

Надеюсь, у вас возник вопрос, и я сожалею о любом плохом английском.

4b9b3361

Ответ 1

Используйте шаблон шаблона - не переопределяйте базовый метод, который должен выполнить некоторую работу, переопределить один конкретный бит, который может либо быть абстрактным или нет-op в базовом классе. (Решение о том, делать ли это не-op или абстрактным, обычно довольно очевидно - действительно ли базовый класс имеет смысл сам по себе, как конкретный класс?)

Похоже, что это в основном шаблон, который вы нашли с помощью UpdateEx - хотя обычно это UpdateImpl или что-то подобное в моем опыте. С моей точки зрения, нет ничего плохого в качестве шаблона - он избегает любой идеи заставить все производные классы написать один и тот же код для вызова базового метода.

Ответ 2

Я думаю, что предложение, которое вы нашли, хорошо.

Единственный метод базового класса, который нельзя избежать вызова из подкласса в конструкторе базового класса.

Ответ 3

Я думаю, что наличие не виртуального базового элемента, который вызывает виртуальный "крючок", который может быть расширен, является наиболее распространенным решением для такого рода проблем.

В зависимости от вашего варианта использования вы можете вместо этого использовать event, но обычный шаблон для реализации события должен иметь виртуальный OnEvent метод, который подклассы могут переопределять вместо добавления обработчика события, поэтому в ваш пример дела сводится к тому же.

Ответ 4

Мне потребовалось немного времени, чтобы посмотреть, как выглядят Update и UpdateEx. Вот пример кода, который может помочь другим.

public class BaseClass
{
    // This is the Update that class instances will use, it 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();

public class ConcreteClass : BaseClass
{
    protected override void UpdateEx()
    {
        // implementation to be added to the BaseClass Update();
    }
}

Любой экземпляр ConcreteClass будет использовать реализацию BaseClass Update() вместе с тем, однако ConcreteClass расширяет его с помощью UpdateEx().