Я хочу знать, что считается лучшим способом возвращения, когда у меня есть if
заявление.
Пример 1:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
else
{
myString = "Name " + myString;
// Do something more here...
return true;
}
}
Пример 2:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
myString = "Name " + myString;
// Do something more here...
return true;
}
Как вы можете видеть в обоих примерах, функция вернется, true/false
но стоит ли ставить else
оператор так, как в первом примере, или лучше его не ставить?
else
.Ответы:
Пример 2 известен как защитный блок. Лучше всего возвращать / выдавать исключение раньше, если что-то пошло не так (неправильный параметр или недопустимое состояние). В нормальном логическом потоке лучше использовать Пример 1
источник
Мой личный стиль - использовать сингл
if
для защитных блоков иif
/else
в реальном коде обработки метода.В этом случае вы используете в
myString == null
качестве защитного условия, поэтому я бы предпочел использовать одинif
шаблон.Рассмотрим код, который немного сложнее:
Пример 1:
Пример 2:
В примере 1 и охранник, и остальная часть метода находятся в форме
if
/else
. Сравните это с Примером 2, где защитный блок находится в единственнойif
форме, тогда как остальная часть метода использует формуif
/else
. Лично я считаю, что пример 2 легче понять, в то время как пример 1 выглядит неопрятно и с чрезмерным отступом.Обратите внимание, что это надуманный пример, и вы можете использовать
else if
операторы для его очистки, но я стремлюсь показать разницу между защитными блоками и реальным кодом обработки функций.Приличный компилятор должен генерировать одинаковый вывод для них обоих в любом случае. Единственная причина для использования одного или другого - это личные предпочтения или соответствие стилю существующего кода.
источник
лично я предпочитаю второй метод. Я чувствую, что он короче, имеет меньше отступов и легче для чтения.
источник
Моя личная практика заключается в следующем:
Например:
Например:
Правило «одного выхода» также помогает, когда для расчета требуются внешние ресурсы, которые вы должны высвободить, или говорится, что вы должны сбросить их перед выходом из функции; иногда они добавляются позже во время разработки. С несколькими выходами внутри алгоритма намного сложнее правильно расширить все ветви. (И если могут возникать исключения, то сброс / сброс также следует поместить в блок finally, чтобы избежать побочных эффектов в редких исключительных случаях ...).
Похоже, ваш случай попадает в категорию «быстрый выход перед реальной работой», и я бы написал это так же, как в примере 2.
источник
Я предпочитаю использовать охранные блоки везде, где могу, по двум причинам:
Вообще говоря, я предпочитаю видеть методы, в которых основная функциональность метода ясна и минимальна. Блоки охраны помогают визуально сделать это возможным.
источник
Мне нравится подход "Fall Through":
У действия есть определенное условие, все остальное - просто возврат по умолчанию.
источник
Если бы у меня было единственное условие, я бы не тратил слишком много времени на размышления о стиле. Но если у меня несколько условий охраны, я бы предпочел style2
Picuture это. Предположим, что тесты сложные, и вы действительно не хотите связывать их в одно условие if-ORed, чтобы избежать сложности:
против
Здесь есть два основных преимущества
Вы разделяете код в одной функции на два визуально логических блока: верхний блок проверок (защитные условия) и нижний блок исполняемого кода.
Если вам нужно добавить / удалить одно условие, вы уменьшите свои шансы испортить всю лестницу if-elseif-else.
Еще одно незначительное преимущество - у вас есть наименьшее количество скобок для ухода.
источник
Это должно быть вопросом, который звучит лучше.
выражается лучше, чем
для маленьких методов это не будет иметь большого значения, но для больших составных методов это может усложнить понимание, поскольку не будет должным образом отделено
источник
do something
включает в себя возврат. Если нет, второй код будет выполнятьсяdo somethingelse
независимо отif
предиката, который не работает как первый блок.Я нахожу пример 1 раздражающим, потому что пропущенный оператор return в конце функции, возвращающей значение, сразу вызывает флаг «Подождите, что-то не так». Так что в таких случаях я бы пошел с примером 2.
Тем не менее, как правило, в этом участвует больше, в зависимости от назначения функции, например, обработка ошибок, ведение журнала и т. Д. Так что я отвечаю на этот вопрос Лорану Кедвесу, и обычно у меня есть одна точка выхода в конце, даже ценой дополнительной переменной флага. В большинстве случаев это облегчает обслуживание и последующие расширения.
источник
Когда ваш
if
оператор всегда возвращается, нет смысла использовать else для оставшегося кода в функции. Это добавляет дополнительные строки и дополнительные отступы. Добавление ненужного кода затрудняет чтение, и, как всем известно, чтение кода - это сложная задача .источник
В вашем примере
else
это явно не нужно, НО ...Быстро просматривая строки кода, глаза обычно смотрят на фигурные скобки и отступы, чтобы получить представление о потоке кода; прежде чем они на самом деле обосноваться на самом коде. Следовательно, написание
else
скобок и отступов вокруг второго блока кода позволяет читателю быстрее увидеть, что это ситуация «A или B», когда один или другой блок будет выполняться. То есть читатель видит фигурные скобки и отступы ДО того, как они увидятreturn
после инициалаif
.На мой взгляд, это один из тех редких случаев, когда добавление чего-то избыточного в код на самом деле делает его БОЛЕЕ читаемым, а не меньшим.
источник
Я бы предпочел пример 2, потому что сразу видно, что функция возвращает что-то . Но даже более того, я бы предпочел вернуться из одного места, например так:
С этим стилем я могу:
Смотри сразу, что я что-то возвращаю.
Поймать результат каждого вызова функции только с одной точкой останова.
источник
Мой личный стиль имеет тенденцию идти
Использование закомментированных
else
выражений для обозначения потока программы и обеспечения его читабельности, но при этом избегаются массивные отступы, которые могут легко появиться на экране при большом количестве шагов.источник
else
включенными предложениями, я бы выбрал последнее, потому что компилятор также будет эффективно их игнорировать. Хотя это будет зависеть от того,else if
не увеличит ли отступ больше, чем за один раз - если бы это произошло, я бы с тобой согласился Но мой выбор -else
полностью отказаться, если этот стиль будет разрешен.Я бы написал
Я предпочитаю этот стиль, потому что наиболее очевидно, что я бы вернулся
userName != null
.источник
myString
результате. Я просто копирую функцию из OP. Я изменю это на что-то, что выглядит более реальным. Булев тест является тривиальным и не должен быть проблемой.Мое эмпирическое правило заключается в том, чтобы либо выполнить возврат-возвращение без else (в основном для ошибок), либо выполнить полную цепочку if-else-if для всех возможностей.
Таким образом, я стараюсь не слишком увлекаться своими ветвлениями, поскольку всякий раз, когда я в конечном итоге это делаю, я кодирую логику приложения в свои if, что усложняет их поддержку (например, если enum OK или ERR и я пишу все свои if пользуясь тем фактом, что! OK <-> ERR, в задницу становится больно добавлять третий вариант в перечисление в следующий раз.)
В вашем случае, например, я бы использовал простой if, так как «return if null» обязательно будет распространенным шаблоном, и маловероятно, что вам придется беспокоиться о третьей возможности (в дополнение к null / not null) в будущем.
Тем не менее, если бы тест проводился с более тщательной проверкой данных, я бы вместо этого сделал ошибку, чтобы получить полное «если-еще».
источник
Я думаю, что в Примере 2 есть много подводных камней, которые в будущем могут привести к непреднамеренному коду. Во-первых, в основе этого лежит логика, окружающая переменную myString. Поэтому , чтобы быть явным, все испытания условий должно происходить в блоке учета кода для известны и по умолчанию / неизвестной логики.
Что делать, если позже в примере 2 непреднамеренно был введен код, который значительно изменил результат:
Я думаю, что с
else
блоком, следующим сразу за проверкой на ноль, программисты, которые добавили усовершенствования в будущие версии, добавили бы всю логику вместе, потому что теперь у нас есть строка логики, которая была непреднамеренной для исходного правила (возвращая, если значение равно значение NULL).Я глубоко верю в это некоторым руководствам C # по Codeplex (ссылка на них здесь: http://csharpguidelines.codeplex.com/ ), в которых говорится следующее:
«Добавьте описательный комментарий, если блок по умолчанию (иное) должен быть пустым. Более того, если этот блок не должен быть достигнут, выведите исключение InvalidOperationException для обнаружения будущих изменений, которые могут попасть в существующие случаи. Это гарантирует лучший код, потому что все пути, по которым может пройти код, были продуманы ".
Я думаю, что это хорошая практика программирования, когда при использовании таких логических блоков всегда добавляется блок по умолчанию (if-else, case: default), чтобы явно учитывать все пути кода и не оставлять код открытым для непреднамеренных логических последствий.
источник
myString
значением, а код, следующий заif
блоком, является результирующей логикой, если строка! = Null. Поэтому, поскольку основное внимание уделяется дополнительной логике, управляющей этим конкретным значением, я думаю, что оно должно быть заключено вelse
блок. В противном случае это открывает потенциал, как я показал, чтобы непреднамеренно отделить логику и ввести непредвиденные последствия. Может случиться не все время, но это действительно был вопрос стиля, основанного на передовом опыте .