Преимущества использования условного оператора?: (Троичный) - PullRequest
100 голосов
/ 22 июля 2010

Каковы преимущества и недостатки оператора?: По сравнению со стандартным оператором if-else.Очевидные из них:

Условный?: Оператор

  • Короче и более кратко при работе с прямыми сравнениями значений и присвоениями
  • Кажется, не такой гибкий, как конструкция if / else

Стандартный If / Else

  • Может применяться кдругие ситуации (например, вызовы функций)
  • Часто бывают неоправданно длинными

Кажется, что читаемость может отличаться для каждого в зависимости от оператора.Некоторое время после первого обращения к оператору?: Мне потребовалось некоторое время, чтобы разобраться, как именно это работает.Вы бы порекомендовали использовать его везде, где это возможно, или придерживаться, если / еще, учитывая, что я работаю со многими непрограммистами?

Ответы [ 17 ]

119 голосов
/ 22 июля 2010

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

Хороший пример:

int result = Check() ? 1 : 0;

Плохой пример:

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;
50 голосов
/ 23 июля 2010

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

В таких языках, как C ++ и C #, вы можете определять локальное чтение только для чтенияполя (в теле метода), использующие их.Это невозможно с обычным оператором if / then, потому что значение поля «только для чтения» должно быть назначено в этом единственном операторе:

readonly int speed = (shiftKeyDown) ? 10 : 1;

не совпадает с:

readonly int speed;  
if (shifKeyDown)  
    speed = 10;    // error - can't assign to a readonly
else  
    speed = 1;     // error  

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

MoveCar((shiftKeyDown) ? 10 : 1);

... может генерировать меньше кода, чемнеобходимость вызывать один и тот же метод дважды:

if (shiftKeyDown)
    MoveCar(10);
else
    MoveCar(1);

Конечно, это также более удобная и лаконичная форма (меньше печатания, меньше повторений и может уменьшить вероятность ошибок, если вам придется дублировать куски кодав if / else).В чистых «общих шаблонах», подобных этому:

object thing = (reference == null) ? null : reference.Thing;

... просто читать / анализировать / понимать (если вы привыкли к нему) просто быстрее, чем многословный эквивалент if / else, так что это может помочь вам быстрее «прогнать» код.

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

13 голосов
/ 23 июля 2010

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

if (a > 0)
    answer = compute(a, b, c, d, e);
else
    answer = compute(-a, b, c, d, e);

С помощью троичного оператора это может быть достигнуто с помощью следующего.

answer = compute(a > 0 ? a : -a, b, c, d, e); 
12 голосов
/ 23 июля 2010

Действительно классное использование:

x = foo ? 1 :
    bar ? 2 :
    baz ? 3 :
          4;
12 голосов
/ 22 июля 2010

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

6 голосов
/ 23 июля 2010

Условный оператор отлично подходит для коротких условий, например:

varA = boolB ? valC : valD;

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

doSomeStuffToSomething(shouldSomethingBeDone()
    ? getTheThingThatNeedsStuffDone()
    : getTheOtherThingThatNeedsStuffDone());

Однако большое преимущество использования блоков if / else (и почему я предпочитаю их) состоит в том, что проще прийти позже и добавить некоторую дополнительную логику в ветку,

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else {
doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}

или добавить другое условие:

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else if (shouldThisOtherThingBeDone()){
    doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}

Итак, в конце концов, речь идет об удобстве для вас сейчас (короче использовать:?) И удобстве для вас (и других) позже. Это суждение ... но, как и все другие вопросы форматирования кода, единственное реальное правило - быть последовательным и быть вежливым с теми, кто должен поддерживать (или оценивать!) Ваш код.

(весь код скомпилирован с глазом)

5 голосов
/ 03 декабря 2015

Хотя приведенные выше ответы верны, и я согласен с важностью читабельности, есть еще два момента, которые следует учитывать:

  1. В C # 6 вы можете использовать методы с выражением тела.

Это делает особенно лаконичным использование троичного:

string GetDrink(DayOfWeek day) 
   => day == DayOfWeek.Friday
      ? "Beer" : "Tea";
  1. Поведение отличается, когда дело доходит до неявного преобразования типов.

Если у вас есть типы T1 и T2, которые могут быть неявно преобразованы в T, то приведенные ниже не работают:

T GetT() => true ? new T1() : new T2();

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

С другой стороны, приведенная ниже версия if/else работает:

T GetT()
{
   if (true) return new T1();
   return new T2();
}

потому что T1 конвертируется в T и T2

5 голосов
/ 23 июля 2010

При использовании троичного оператора нужно понимать, что это выражение, а не выражение.

В функциональных языках, таких как схема, различия не существует:

(if (> ab) ab)

Условный?: Оператор "Кажется, чтогибкий как конструкция if / else "

В функциональных языках это так.

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

5 голосов
/ 17 февраля 2016

Иногда это может облегчить чтение значения bool на первый взгляд:

// With
button.IsEnabled = someControl.HasError ? false : true;

// Without
button.IsEnabled = !someControl.HasError;
4 голосов
/ 23 июля 2010

Я бы рекомендовал ограничить использование троичного оператора (? :) простым однострочным присваиванием логики if / else.Нечто похожее на этот шаблон:

if(<boolCondition>) {
    <variable> = <value>;
}
else {
    <variable> = <anotherValue>;
}

Можно легко преобразовать в:

<variable> = <boolCondition> ? <value> : <anotherValue>;

Я бы не использовал троичный оператор в ситуациях, когда требуется if / else if / else, вложенный if /иначе, или логика ветки if / else, которая приводит к вычислению нескольких строк.Применение троичного оператора в этих ситуациях может привести к нечитаемому, запутанному и неуправляемому коду.Надеюсь, это поможет.

...