Преимущества использования условного оператора?: (Троичный)

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

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

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

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

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

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

97 голосов | спросил 5 revs, 5 users 68%
KChaloux
1 Jam1000000amThu, 01 Jan 1970 03:00:00 +030070 1970, 03:00:00

16 ответов


0

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

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

int result = Check() ? 1 : 0;

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

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

В таких языках, как 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, так что это может помочь вам быстрее "прогнать" код.

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

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); 
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

x = foo ? 1 :
    bar ? 2 :
    baz ? 3 :
          4;
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

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());
}

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

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

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

(если (> a b) a b)

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

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

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

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

// Without
button.IsEnabled = !someControl.HasError;
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

Дополнительный интерес для вас может представлять ?? Оператор .

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

Преимущество условного оператора заключается в том, что он является оператором. Другими словами, он возвращает значение. Поскольку if является оператором, он не может возвращать значение.

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

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

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

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

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

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

Есть некоторые преимущества в использовании? оператор в например. MS Visual C ++, но это действительно специфичная для компилятора вещь. В некоторых случаях компилятор может оптимизировать условную ветвь.

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

Сценарий, который я чаще всего использую, это для значений по умолчанию и особенно для возвратов

return someIndex < maxIndex ? someIndex : maxIndex;

Это действительно единственные места, где я нахожу это хорошим, но для них я делаю.

Хотя, если вы ищете логическое значение, иногда это может выглядеть уместно:

bool hey = whatever < whatever_else ? true : false;

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

bool hey = (whatever < whatever_else);
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

Если вам нужно несколько веток в одном условии, используйте if:

if (A == 6)
  f(1, 2, 3);
else
  f(4, 5, 6);

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

f( (A == 6)? 1: 4, (B == 6)? 2: 5, (C == 6)? 3: 6 );

Кроме того, вы можете использовать троичный оператор при инициализации.

const int i = (A == 6)? 1 : 4;

Делать это с if очень грязно:

int i_temp;
if (A == 6)
   i_temp = 1;
else
   i_temp = 4;
const int i = i_temp;

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

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

Тернарный оператор может быть включен в r-значение, тогда как if-then-else не может; с другой стороны, if-then-else может выполнять циклы и другие операторы, тогда как троичный оператор может выполнять только (возможно, void) r-значения.

В связанной заметке & & и || операторы допускают некоторые шаблоны выполнения, которые сложнее реализовать с помощью if-then-else. Например, если у вас есть несколько функций для вызова и вы хотите выполнить фрагмент кода, если какая-либо из них не удалась, это можно сделать, используя & & оператор. Выполнение этого без этого оператора потребует избыточного кода, перехода или дополнительной переменной флага.

ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57
0

С C # 7 вы можете использовать новый ref locals для упрощения условного присвоения ref-совместимых переменных. Так что теперь вы можете не только:

int i = 0;

T b = default(T), c = default(T);

// initialization of C#7 'ref-local' variable using a conditional r-value⁽¹⁾

ref T a = ref (i == 0 ? ref b : ref c);

... но также чрезвычайно замечательно:

// assignment of l-value⁽²⁾ conditioned by C#7 'ref-locals'

(i == 0 ? ref b : ref c) = a;

Эта строка кода присваивает значение a любому из b или c, в зависимости от значения i.



Примечания
1. r-value - это правая сторона присваивания, значение, которое присваивается.
2. l-value - это левая сторона присваивания, переменная, которая получает назначенное значение.
ответил anand tripathi 29 PM00000060000005731 2015, 18:42:57

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132