С# — полный возврат из базового метода

У меня есть виртуальный базовый метод void Action(), который переопределен в производном классе.

Первым шагом в действии является вызов base.Action(). Если в базовом методе возникает ситуация, я не хочу, чтобы остальная часть производного метода обрабатывалась.

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

В настоящее время я рассматриваю возможность изменения void на bool и использования его в качестве управления потоком, но мне было интересно, есть ли какие-либо другие шаблоны проектирования, которые я мог бы использовать.


person Talib    schedule 28.05.2012    source источник
comment
Нет, это не ошибка, поэтому исключения не будут работать.   -  person Talib    schedule 28.05.2012
comment
Извините, выигрыш (предыдущее сообщение о том, что решение не нужно, удалено), мне все еще нужно решение, система становится довольно сложной. По сути, где-то в коде есть переменная credits_available. Я хотел бы иметь возможность отключить все действия в базовом классе, если нет доступных кредитов. Я хотел бы иметь возможность сделать это без дублирования кода производным классом.   -  person Talib    schedule 28.05.2012


Ответы (3)


Не используйте его с возвращаемым типом void, но можно, скажем, bool

public class Base
{
    public virtual bool Action()
    {
       ..
       return boolean-value.
    }
}

public class Child : Base
{
    public override bool Action()
    {
       if(!base.Action()) 
         return false;

       ....
       return boolean-value;
    }
}

Или, если это исключительная ситуация, создайте исключение, как предлагают другие.

person Tigran    schedule 28.05.2012
comment
Это немного запутанно, так как предоставляет ненужную реализацию потребителю класса. - person Slugart; 28.05.2012
comment
@Slugart: о какой реализации вы говорите? - person Tigran; 28.05.2012
comment
Извините, я имел в виду детали реализации - теперь действие раскрывает тот факт, что оно возвращает логическое значение. Что это значит для потребителя производного класса? - person Slugart; 28.05.2012
comment
Что означает на самом деле, можно уточнить в документации/комментариях к функции. ЕСЛИ это хороший или плохой дизайн, зависит от конкретной архитектуры/дизайна программы. Я понятия не имею, в каком контексте будет использоваться этот код, поэтому просто предложу одно из возможных решений. - person Tigran; 28.05.2012
comment
Хороший это или плохой дизайн также зависит от того, соблюдает ли он принципы объектно-ориентированного дизайна, одним из которых является инкапсуляция. Я просто пытался указать, что в этом дизайне есть детали реализации. - person Slugart; 28.05.2012
comment
Я думаю, что это самое простое решение, без чрезмерного усложнения системы. Мне просто нужно будет правильно задокументировать это. С другой стороны, просто любопытно, может ли производный метод по-прежнему иметь возвращаемый тип как void, поскольку возвращаемое значение никогда не будет использоваться. - person Talib; 28.05.2012
comment
@Talib: Нет, производный метод не может изменить возвращаемый тип метода, который он переопределяет. Честно говоря, если это деталь реализации, я бы постарался не размещать ее в общедоступном API. - person Jon Skeet; 28.05.2012

Это ошибка "ситуация"? Если это так, просто заставьте его генерировать исключение и не перехватывайте исключение в переопределении.

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

Другой вариант — использовать шаблон метода шаблона:

public abstract class FooBase
{
    public void DoSomething()
    {
        DoUnconditionalActions();
        if (someCondition)
        {
            DoConditionalAction();
        }
    }

    protected abstract void DoConditionalAction();
}

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

Если ни один из этих вариантов не подходит, вам нужно будет предоставить нам более конкретную информацию о том, чего вы пытаетесь достичь.

person Jon Skeet    schedule 28.05.2012

Сгенерируйте исключение в базовом методе. Он выйдет из каждого метода, который его вызвал, пока не будет пойман.

person Guffa    schedule 28.05.2012
comment
Выбрасывать исключение в часто вызываемый метод — не очень хорошая идея. - person Mert Akcakaya; 28.05.2012
comment
@Mert: это хорошая идея в исключительной ситуации, но плохая идея для потока управления в большинстве случаев. - person Tigran; 28.05.2012
comment
@Mert: часто выбрасывать исключения нехорошо, но исключение выдается только в случае возникновения ситуации, как выразился ОП. Это не происходит каждый раз при вызове метода, поскольку обычный поток заключается в выполнении остальной части кода в производном методе. - person Guffa; 28.05.2012
comment
@Guffa: В данном случае ситуация не является ошибкой. В настоящее время я рассматриваю возможность изменения void на bool и использования этого в качестве управления потоком, он ищет способ использовать это в управлении потоком, а условия управления потоком возникают очень часто, если не каждый раз. - person Mert Akcakaya; 28.05.2012
comment
@Mert: Это твоя интерпретация. Тот факт, что OP использует термин «управление потоком» для обработки того, что код должен делать в разных ситуациях, не означает, что это не может быть ошибкой. - person Guffa; 28.05.2012
comment
@Guffa: Это моя интерпретация? Как вы интерпретируете Нет, это не ошибка, поэтому исключения не сработают – Талиб? Конец дискуссии. - person Mert Akcakaya; 28.05.2012