Это плохая практика использовать return внутри void-метода?

Представьте себе следующий код:

void DoThis()
{
    if (!isValid) return;

    DoThat();
}

void DoThat() {
    Console.WriteLine("DoThat()");
}

Можно ли использовать возврат внутри метода void? Есть ли какие-либо потери производительности? Или лучше написать такой код:

void DoThis()
{
    if (isValid)
    {
        DoThat();
    }
}
 STW16 авг. 2009 г., 06:27
представить код? Почему? Это прямо там! :-D
 Dscoduc16 авг. 2009 г., 05:52
Как насчет: void DoThis () {if (isValid) DoThat (); }
 Cheung02 апр. 2015 г., 04:44
Это хороший вопрос, я всегда думаю, что это хорошая практика - использовать return; выйти из метода или функции. Особенно в методе интеллектуального анализа данных LINQ, имеющем несколько результатов IQueryable <T>, и все они зависят друг от друга. Если один из них не дал результата, предупредите и выйдите.

Ответы на вопрос(10)

но никогда не пишите «если» без скобок.

Всегда

if( foo ){
    return;
}

Это более читабельно; и вы никогда не будете случайно предполагать, что некоторые части кода находятся в этом утверждении, когда это не так.

 Charles Bretana16 авг. 2009 г., 05:44
читабельно субъективно. imho, все, что добавляется в ненужный код, делает его менее читабельным ... (Я должен прочитать больше, и затем я удивляюсь, почему это происходит, и теряю время, пытаясь убедиться, что я что-то не пропустил) ... но это мое субъективное мнение
 Scott Dorman16 авг. 2009 г., 05:58
Лучшая причина всегда включать скобки - это не читабельность, а безопасность. Без фигурных скобок для кого-то позже будет легко исправить ошибку, которая требует дополнительных операторов в качестве части if, не уделять достаточно пристального внимания и добавлять их без добавления фигурных скобок. Всегда включая скобки, этот риск устраняется.
 Noon Silk16 авг. 2009 г., 06:14
@ Imagist Я оставлю это личным предпочтениям; и это сделано так, как я предпочитаю :)
 Imagist16 авг. 2009 г., 06:11
Шелковистый, пожалуйста, нажмите Enter, прежде чем ваш{, Это выстраивает ваш{ с твоим} в том же столбце, что значительно облегчает чтение (гораздо проще найти соответствующие открывающие / закрывающие скобки).
 supercat10 июл. 2014 г., 18:01
Если каждая закрывающая скобка соответствует открытой скобкекоторый находится на том же уровне отступазатем визуально различая, какиеif утверждения требуют тесных скобок будет легко, и, следовательно, имеяif операторы контроля одного заявления будут в безопасности. Оттяните открытую скобу обратно к линии сif сохраняет линию вертикального пространства на каждом множественном утвержденииif, но потребует использования ненужной закрывающей скобки.

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

Также проверьте ответы на аналогичный вопрос:Должен ли я использовать оператор return / continue вместо if-else?

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

но это не имеет ничего общего с возвратом из функции void, это просто потому, что второй код более прямой. Но возвращение из функции void вполне нормально.

однако второй фрагмент кода более читабелен и, следовательно, проще в обслуживании.

 Pete Hodgson16 авг. 2009 г., 10:55
Я тоже не согласен. Оговорки, которые рано или поздно выходят из функции, обычно считаются хорошей вещью, помогая читателю понять реализацию.
 cdmckay16 авг. 2009 г., 07:58
Я не согласен с этим. Увеличение вложенности не улучшает читаемость. Первый фрагмент кода использует оператор «guard», который является вполне понятным шаблоном.
 Paul Sasik16 авг. 2009 г., 05:19
Рассел, я не согласен с твоим мнением, но тебе не следовало за него голосовать. +1, чтобы выровнять это. Кстати, я считаю, что булево тестирование и возврат в одну строку, за которой следует пустая строка, является четким указанием того, что происходит. например Первый пример Родриго.

Использование возврата в середине метода, недействительного или иного, является очень плохой практикой, по причинам, которые были довольно четко сформулированы почти сорок лет назад покойным Эдсгером В. Дейкстрой, начиная с хорошо известного "GOTO-заявления, считающегося вредным". и продолжая в разделе «Структурированное программирование» Дала, Дейкстры и Хоара.

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

«Заявление GOTO считается вредным» и «Структурированное программирование» положили начало революции «Структурированное программирование» 1970-х годов. Эти две части являются причинами того, что у нас есть if-then-else, while-do и другие явные конструкции управления сегодня, и почему операторы GOTO на языках высокого уровня находятся в списке вымирающих видов. (Мое личное мнение, что они должны быть в списке вымерших видов.)

Стоит отметить, что Message Flow Modulator, первый образец военного программного обеспечения, который когда-либо проходил приемочное тестирование с первой попытки, без отклонений, отказов или слов «да, но», был написан на языке, который даже не имел GOTO заявление.

Стоит также упомянуть, что Никлаус Вирт изменил семантику оператора RETURN в Oberon-07, последней версии языка программирования Oberon, сделав его завершающим элементом объявления типизированной процедуры (т. Е. Функции), а не выполнимый оператор в теле функции. Его объяснение изменения говорит, что он сделал это именно потому, что предыдущая формаБЫЛ нарушение принципа единого выхода структурированного программирования.

 John Saunders16 авг. 2009 г., 08:20
@John: мы преодолели запрет Dykstra о множественных возвратах как раз в то время, когда мы прошли над Pascal (большинство из нас, так или иначе).
 nairdaen16 авг. 2009 г., 08:09
Как исключения здесь подходят?
 John R. Strohm16 авг. 2009 г., 08:32
@nairdaen: В этом квартале все еще существуют противоречия в отношении исключений. Моя рекомендация такова: если разрабатываемая система ДОЛЖНА решить проблему, которая вызвала первоначальное исключительное состояние, и я не против разозлить парня, которому придется писать этот код, я скину исключение. Потом на меня наорают, потому что парень не удосужился поймать исключение, приложение рухнуло во время тестирования, и я объясняю, ПОЧЕМУ ему нужно решить проблему, и все решается снова.
 Jason Williams16 авг. 2009 г., 08:46
Существует большая разница между защитными заявлениями и готовностью. Зло gotos в том, что они могут прыгать куда угодно, поэтому может быть очень запутанным, чтобы распутать и запомнить. Защитные операторы прямо противоположны - они предоставляют стробированную запись в метод, после чего вы знаете, что работаете в «безопасной» среде, сокращая количество вещей, которые вы должны учитывать при написании остальной части кода (например, «Я знаю, что этот указатель никогда не будет нулевым, поэтому мне не нужно обрабатывать этот случай во всем коде»).
 kyoryu16 авг. 2009 г., 08:30
Случаи, когда требуются множественные возвраты, часто являются признаками того, что метод пытается сделать слишком много, и его следует сократить. Я не собираюсь заходить так далеко, как Джон, и утверждение возврата как часть проверки параметров может быть разумным исключением, но я понимаю, откуда приходит идея.

Ваш метод ожидает, что объект не будет нулевым, и это не тот случай, поэтому вы должны выбросить исключение и позволить вызывающей стороне обработать это.

Но в противном случае раннее возвращение - это не плохая практика.

 WizardHammer18 мар. 2019 г., 19:14
Ответ не отвечает на вопрос. Вопрос является пустым методом, поэтому ничего не возвращается. Кроме того, методы не имеют параметров. Я получаю смысл не возвращать нуль, если тип возвращаемого значения - объект, но это не относится к этому вопросу.

ие от вложенного кода): если другой программист добавляет код в вашу функцию, он работает в более безопасной среде.

Рассмотреть возможность:

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }
}

против:

void MyFunc(object obj)
{
    if (obj == null)
        return;

    obj.DoSomething();
}

Теперь представьте, что другой программист добавляет строку: obj.DoSomethingElse ();

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }

    obj.DoSomethingElse();
}

void MyFunc(object obj)
{
    if (obj == null)
        return;

    obj.DoSomething();
    obj.DoSomethingElse();
}

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

Конечно, хороший программист не совершает подобных ошибок (часто). Но профилактика лучше лечения - мы можем написать код таким образом, чтобы полностью устранить этот потенциальный источник ошибок. Вложенность добавляет сложности, поэтому лучшие практики рекомендуют рефакторинг кода, чтобы уменьшить вложенность.

 Jason Williams16 авг. 2009 г., 11:09
Я спорю вблагоприятствовать уменьшенного вложения! :-)
 Skrim16 авг. 2009 г., 08:58
Да, но, с другой стороны, несколько уровней вложенности с их условиями делают код еще более подверженным ошибкам, логику труднее отслеживать и, что еще важнее, труднее отлаживать. Плоские функции - меньшее зло, ИМО.
 Phil Cooper07 окт. 2015 г., 17:00
Я согласен с этим. Кроме того, с точки зрения рефакторинга, рефакторинг метода проще и безопаснее, если obj становится структурой или что-то, что вы можете гарантировать, не будет нулевым.

инвертироватьif заявления для уменьшения вложенности.

А уменьшение вложенности ваших методов повышает удобочитаемость кода и удобство сопровождения.

На самом деле, если у вас есть метод void без какого-либо оператора возврата, компилятор всегда будет генерироватьповторная инструкция в конце этого.

 bdd16 авг. 2009 г., 06:03
Коротко, мило и правильно!

Википедия:

В компьютерном программировании защита - это логическое выражение, которое должно принимать значение true, если выполнение программы продолжается в рассматриваемой ветви.

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

Итак, в общем, это так:

void DoThis()
{
  if (guard1) return;
  if (guard2) return;
  ...
  if (guardN) return;

  DoThat();
}

Я думаю, что это гораздо более читабельно, чем:

void DoThis()
{
  if (guard1 && guard2 && guard3)
  {
    DoThat();
  }
}

Ваш ответ на вопрос