К тройной или не к тройной?

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

Каковы ваши чувства к этому? Какой интересный код вы видели с его помощью?

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

 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 просто b / 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 

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

Оператор Ternary ?: Является просто функциональным эквивалентом процедурной конструкции 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; } 

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

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

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

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

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

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

 return x ? "Yes" : "No"; 

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

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

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

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

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

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

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

Который установит x в y считая y не NULL . Хорошая вещь.

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

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

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

Другими мерами, такими как читаемость, ремонтопригодность и DRY (Don’t-Repeat-Yourself), любой выбор может оказаться лучше, чем другой.

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

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

 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 , но он имеет свое место для выражения return или внутри выражения:

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

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

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

(Взлом дня)

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

Тогда вы можете сделать if-then-else как выражение:

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

Я думаю, что тройной оператор следует использовать, когда это необходимо. Это, очевидно, очень субъективный выбор, но я считаю, что простое выражение (особенно как выражение возврата) намного яснее, чем полный тест. Пример в C / 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; 

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

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

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

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

$ var = (simple> test? simple_result_1: simple_result_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 / else.

Несовпадение в моей книге было бы большим НЕТ-НЕТ.

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

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

 expr ?: default 

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

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

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

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

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

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

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

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

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

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

  • Почему в C ++ нет выражения удаления места размещения?
  • Давайте будем гением компьютера.