Вопрос

Я лично сторонник тернарного оператора:() ?:;Я понимаю, что он имеет свое место, но я встречал многих программистов, которые категорически против его использования, а некоторые используют его слишком часто.

Какие у вас чувства по этому поводу?Какой интересный код вы видели, используя его?

Это было полезно?

Решение

Используйте его для только простые выражения:

int a = (b > 10) ? c : d;

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

int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;

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

int a = (b > 10) ? some_value                 
                 : another_value;

Другие советы

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

Я люблю их, особенно в типобезопасных языках.

Я не понимаю, как это:

int count = (condition) ? 1 : 0;

это сложнее, чем это:

int count;

if (condition)
{
  count = 1;
} 
else
{
  count = 0;
}

редактировать -

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

С цепочкой меня устраивает, а с вложенностью не так уж и много.

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

x = (y < 100) ? "dog" :
    (y < 150) ? "cat" :
    (y < 300) ? "bar" : "baz";

скорее, чем

     if (y < 100) { x = "dog"; } 
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; } 
else              { x = "baz"; }

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

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

x =   if (y < 100) then "dog"
    elif (y < 150) then "cat"
    elif (y < 300) then "bar"
    else                "baz"
    end

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

Тройной ?: оператор является просто функциональным эквивалентом процедурного if построить.Итак, пока вы не используете вложенные ?: выражений, здесь применяются аргументы за/против функционального представления любой операции.Но вложение троичных операций может привести к тому, что код станет совершенно запутанным (упражнение для читателя:попробуйте написать синтаксический анализатор, который будет обрабатывать вложенные тернарные условия, и вы оцените их сложность).

Но существует множество ситуаций, когда консервативное использование ?: оператор может привести к коду, который на самом деле Полегче читать, чем иначе.Например:

int compareTo(Object object) {
    if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
       return 1;
    if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
       return -1;
    else
      return 0;              
}

Теперь сравните это с этим:

int compareTo(Object object) {
    if(isLessThan(object))
        return reverseOrder ? 1 : -1;         
    else(isGreaterThan(object))
        return reverseOrder ? -1 : 1;
    else        
       return 0;              
}

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

На самом деле это вопрос стиля;Подсознательные правила, которым я склонен следовать, таковы:

  • Оцените только 1 выражение - так foo = (bar > baz) ? true : false, но нет foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • Если я использую его для логики отображения, например. <%= (foo) ? "Yes" : "No" %>
  • Используйте его только для назначения;никогда не протекайте логику (поэтому никогда (foo) ? FooIsTrue(foo) : FooIsALie(foo) ) Логика потока в троичной системе сама по себе является ложью, игнорируйте последний пункт.

Мне он нравится, потому что он лаконичен и элегантен для простых операций присваивания.

Как и на многие вопросы, связанные с мнением, ответ неизбежен: это зависит

Для чего-то вроде:

return x ? "Yes" : "No";

Я думаю, что это много более кратко (и для меня быстрее разбирать), чем:

if (x) {
    return "Yes";
} else {
    return "No";
}

Теперь, если ваше условное выражение сложное, то тернарная операция — не лучший выбор.Что-то вроде:

x && y && z >= 10 && s.Length == 0 || !foo

не является хорошим кандидатом на роль тернарного оператора.

Кстати, если вы программист на C, GCC на самом деле имеет расширение это позволяет вам исключить часть тройной системы, если она истинна, например:

/* 'y' is a char * */
const char *x = y ? : "Not set";

Который установит x к y предполагая y не является NULL.Хорошая вещь.

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

В других случаях кажется, что тернарный оператор снижает ясность.

По мере цикломатическая сложность, использование if операторы или тернарный оператор эквивалентны.Таким образом, по этой мере ответ таков: нет, сложность будет точно такой же, как и раньше.

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

Я использую его довольно часто там, где мне приходится работать в конструкторе (например, в новых конструкциях .NET 3.5 LINQ to XML) для определения значений по умолчанию, когда необязательный параметр имеет значение null.

Надуманный пример:

var e = new XElement("Something",
    param == null ? new XElement("Value", "Default")
                  : new XElement("Value", param.ToString())
);

или (спасибо астерите)

var e = new XElement("Something",
    new XElement("Value",
        param == null ? "Default"
                      : param.ToString()
    )
);

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

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

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

Я согласен с jmulder:его не следует использовать вместо if, но он имеет место для возвращаемого выражения или внутри выражения:

echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;

Первое — это всего лишь пример, следует использовать лучшую поддержку множественного числа в i18n!

(Хак дня)

#define IF(x) x ?
#define ELSE :

Затем вы можете использовать if-then-else как выражение:

int b = IF(condition1)    res1
        ELSE IF(condition2)  res2
        ELSE IF(conditions3) res3
        ELSE res4;

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

Я думаю, что тернарный оператор следует использовать при необходимости.Очевидно, это очень субъективный выбор, но я считаю, что простое выражение (особенно возвращаемое выражение) гораздо понятнее, чем полный тест.Пример на C/С++:

return (a>0)?a:0;

По сравнению с:

if(a>0) return a;
else return 0;

У вас также есть случай, когда решение находится между тернарным оператором и созданием функции.Например, в Python:

l = [ i if i > 0 else 0 for i in lst ]

Альтернатива:

def cap(value):
    if value > 0:
        return value
    return 0
l = [ cap(i) for i in lst ]

Достаточно, чтобы в Python (как пример) такую ​​идиому можно было видеть регулярно:

l = [ ((i>0 and [i]) or [0])[0] for i in lst ]

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

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

Я видел таких зверей вроде (на самом деле все было намного хуже, поскольку это было isValidDate и также проверялось месяц и день, но я не мог удосуживаться вспомнить все это):

isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

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

Я не против таких мелочей, как:

reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;

или даже немного сложные вещи, такие как:

printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");

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

int result = do_something();
if( result != 0 )
{
  debug_printf("Error while doing something, code %x (%s)\n", result,
                result == 7 ? "ERROR_YES" :
                result == 8 ? "ERROR_NO" :
                result == 9 ? "ERROR_FILE_NOT_FOUND" :
                "Unknown");
}

Я почти никогда не использую тернарный оператор, потому что всякий раз, когда я ДЕЙСТВИТЕЛЬНО его использую, он всегда заставляет меня думать намного больше, чем мне придется думать позже, когда я пытаюсь его поддерживать.

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

Учитывать:

String name = firstName;

if (middleName != null) {
    name += " " + middleName;
}

name += " " + lastName;

Это немного многословно, но я считаю, что это гораздо более читабельно, чем:

String name = firstName + (middleName == null ? "" : " " + middleName)
    + " " + lastName;

или:

String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;

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

Ну, синтаксис у него ужасный.Я считаю функциональные if очень полезными и часто делают код более читабельным.

Я бы предложил сделать макрос, чтобы сделать его более читабельным, но я уверен, что кто-то может придумать ужасный крайний случай (как всегда бывает с CPP).

Только когда:

$var = (простой > тест?простой_результат_1:простой_результат_2);

ЦЕЛОВАТЬ.

Обычно я использую такие вещи:

before:

if(isheader)
    drawtext(x,y,WHITE,string);
else
    drawtext(x,y,BLUE,string);

after:

    drawtext(x,y,isheader==true?WHITE:BLUE,string);

Как отмечали другие, они хороши для коротких простых условий.Мне они особенно нравятся по умолчанию (вроде как || и или использование в javascript и python), например.

int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;

Другое распространенное использование — инициализация ссылки в C++.Поскольку ссылки должны быть объявлены и инициализированы в одном операторе, вы не можете использовать оператор if.

SomeType& ref = pInput ? *pInput : somethingElse;

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

Недавно я видел вариацию тернарных операторов (ну, типа того), которая делает стандартный "() ?Вариант :" кажется образцом ясности:

var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]

или, чтобы привести более наглядный пример:

var Name = ['Jane', 'John'][Gender == 'm'];

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

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

В моей книге, если бы это было большим НЕТ-НЕТ.

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

Мне нравится особый случай тернарного оператора Groovy, называемый оператором Элвиса:?:

expr ?: default

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

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

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

В качестве побочного вопроса я мог бы также отметить, что само его существование на самом деле является некоторой аномалией, поскольку в C сравнительное тестирование является утверждением.В Иконке if Конструкция (как и большая часть Icon) на самом деле является выражением.Итак, вы можете делать такие вещи, как:

x[if y > 5 then 5 else y] := "Y" 

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

Недавно обсуждалась возможность добавления ?: оператора Icon, но несколько человек правильно заметили, что в этом нет абсолютно никакой необходимости из-за способа if работает.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top