Что такое тернарный оператор
Перейти к содержимому

Что такое тернарный оператор

Оператор ?: (справочник по C#)

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

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

Выражение condition должно принимать значение true или false . Если condition принимает значение true , вычисляется выражение consequent , а результат становится результатом операции. Если condition принимает значение false , вычисляется выражение alternative , а результат становится результатом операции. Вычисляется только выражение consequent или alternative .

Начиная с C# 9.0 условные выражения имеют целевой тип. Это значит, что если известен целевой тип условного выражения, типы consequent и alternative должны быть неявно преобразованы в целевой тип, как показано в следующем примере:

Если целевой тип условного выражения неизвестен (например, при использовании ключевого слова var ) или используются C# 8.0 и более ранние версии, типы consequent и alternative должны быть одинаковыми, либо должно поддерживаться неявное преобразование из одного типа в другой:

Условный оператор имеет правую ассоциативность, то есть выражение формы.

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

Условное выражение REF

Начиная с версии C# 7.2 локальные переменные REF и предназначенные только для чтения локальные переменные REF можно присваивать условным образом с использованием условного выражения REF. Кроме того, условное выражение REF можно использовать как возвращаемое ссылочное значение или как аргумент метода .

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

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

Для условного выражения REF типы consequent и alternative должны совпадать. Условные выражения REF не имеют целевого типа.

В следующем примере иллюстрируется использование условного выражения REF:

Условный оператор и оператор if

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

Возможность перегрузки оператора

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

Спецификация языка C#

Дополнительные сведения о функциях, добавленных в C# 7.2 и более поздние версии, см. в следующих заметках о функциях.

Условный JavaScript для экспертов

Осваиваем условные выражения для написания более чистого кода

Условные выражения являются очень важным аспектом в синтаксисе любого языка программирования. Если вы уже некоторое время программируете на каком-либо популярном языке, то уже должны быть знакомы с условными операторами if..elif..else или switch . Они очень полезны для принятия решений в программах.

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

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

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

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

Выражения против инструкций

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

Выражения в JavaScript — это как фразы в грамматике, в то время как инструкции в JavaScript подобны предложениям в грамматике.

Выражение — это любая фраза языка JavaScript, которая может быть вычислена интерпретатором для получения значения.

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

В следующем фрагменте кода представлены некоторые JavaScript выражения:

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

Например: условные выражения, объявление переменных или функций, циклы, throw, return, try/catch/finally и так далее.

Некоторые JavaScript выражения, такие как присваивание или вызов функции могут иметь побочные эффекты и в результате обычно используются в качестве инструкций (инструкции-выражения).

Условия и логические значения

Важнейшим требованием любой условной конструкции является наличие самого условия. Условие — это то, что определяет решение, которое будет принято в программе.

В JavaScript условие может быть любым допустимым выражением. Как правило, каким бы сложным ни было это условное выражение, оно возвращает одно из двух логических значений (booleans): true либо false .

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

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

  • Определение истинного(true) и ложного(false) значения
  • Понимание короткой схемы вычислений в логических операциях

Истинное против ложного

Каждое значение в JavaScript можно классифицировать как истинное или ложное. Ложные значения в JavaScript следующие:

  • '' или "" или « (пустая строка)
  • 0 или -0 (число 0)
  • null
  • undefined
  • NaN
  • false

Все остальные значения, не указанные в этом списке, являются истинными. Всякий раз, когда JavaScript ожидает логическое значение, истинные значения неявно приводятся к true , а ложные — к false .

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

Для этих целей вы также можете использовать оператор логического НЕ ( ! ). Оператор ! преобразует свой операнд в обратное логическое значение, следовательно, он всегда вычисляет логическое значение.

С помощью оператора ! всегда возвращается false для истинных значений и true — для ложных. Чтобы преобразовать значение в соответствующее логическое значение, нужно использовать оператор ! дважды.

Короткая схема вычислений

Для логических операторов И ( && ) и ИЛИ ( || ) необходимо наличие двух операндов. Данные операторы используются для выполнения логических операций над операндами.

Учитывая то, что два операнда являются логическими ( true или false ),

  • операция && возвращает true только в том случае, когда оба операнда имеют значение true , в противном случае возвращается false .
  • операция || возвращает false только в том случае, когда оба операнда имеют значение false , в противном случае возвращается true .

Обратите внимание, что оператор && имеет более высокий приоритет, чем оператор || , поэтому он обычно вычисляется в первую очередь. В связи с этим, если они используются вместе в одном выражении, можно использовать скобки ( () ) для группирования, изменив тем самым порядок вычисления. Рассмотрим следующий фрагмент кода:

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

Операции && и || не всегда возвращают логическое значение. В принципе, они могут произвести любое значение. Вот более краткое описание их поведения на основе короткой схемы вычислений:

  • оператор && сначала вычисляет первый операнд. Если полученное значение истинно, то он вычисляет второй операнд и возвращает его значение. Однако, если значение первого операнда ложно, то оператор просто возвращает ложное значение первого операнда, при этом второй операнд не вычисляется.
  • Оператор || сначала вычисляет первый операнд. Если полученное значение истинно, то возвращается истинное значение первого операнда, второй операнд не вычисляется. Однако, если значение первого операнда ложно, оператор вычисляет второй операнд и возвращает его значение.

Замена инструкций выражениями

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

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

1. Простая инструкция if

Очень простые инструкции if можно легко заменить условными выражениями, опираясь на концепцию короткой схемы вычислений. Рассмотрим следующий фрагмент кода:

В этом фрагменте инструкция if гарантирует, что функция deletePost() будет вызвана, только если условие вернет true .

Простую инструкцию if можно заменить очень простым условным выражением, как показано в следующем фрагменте кода:

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

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

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

2. Инструкции If…Else

Посмотрим на следующий код, определяющий надежность пароля:

Его цель очень проста — проверить, содержит ли пароль более 7 символов. Если да, то присвоить переменной strength значение “Strong” , если нет — “Weak” .

Предыдущий код можно сократить до следующего:

Этот фрагмент кода делает то же самое, что и предыдущий, но в одной строке. Такой код уже выглядит довольно хорошо. Следующий фрагмент проверяет вычисление условного выражения.

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

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

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

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

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

Вот еще одна хорошо известная условная инструкция, которая обычно встречается в кроссбраузерных AJAX-библиотеках.

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

Используя тернарный оператор:

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

Советы и альтернативные приёмы

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

Приведение к логическому значению

Вы уже видели, как явно преобразовать значение JavaScript в эквивалентное логическое значение, используя встроенную функцию Boolean или оператор двойное НЕ ( !! ).

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

  • если значение логическое (boolean), возвращать это значение как есть
  • если значение не логическое, возвращать логическое значение, которое вы выберете по умолчанию — true или false .

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

Законы де Моргана

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

Следующий фрагмент кода демонстрирует данные законы:

Логические тождества

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

Множественные тернарные операторы

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

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

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

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

Заключение

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

Получайте удовольствие от написания кода …

Хорошо знаете JavaScript? Пройдите наш небольшой тест и проверьте свои знания!

Секреты тернарного оператора

Каждый уважающий себя программист С\С++ знает что такое тернарный оператор и большинство использовало его хотя бы раз в своих программах. Но знаете ли вы все секреты тернарного оператора? Какие потенциальные опасности сопряжены с его использованием и какие, казалось бы не связанные с его прямым предназначением, возможности в нем таятся? Эта статья дает вам возможность проверить свои знания и, возможно, узнать что-то новое.
Начнем с небольшого теста.

Скомпилируется ли следующий код? Объясните почему.
1.

Какой будет вывод у следующего кусочка? Почему?
6.

Какие значения будут у переменных a, b и c в результате выполнения следующего кода? Почему?
7.

8. Назовите ситуацию, где нельзя использовать if <. >else , но можно тернарный оператор.
9. Какие потенциальные опасности скрываются в использовании тернарного оператора? В чем их причина?
10. Какие неожиданные использования тернарного оператора приходят вам в голову?

Объяснение

Итак, начнем. Тернарный оператор выделяется из ряда других операторов в С++. Его называют «conditional expression«. Ну а так как это expression, выражение, то как у каждого выражения, у него должен быть тип и value category. Собственно, ответив на вопросы какой тип и value category у тернарных операторов в каждом из первых семи вопросов теста, мы легко решим поставленные задачи.

Здесь начинается самое интересное. Оказывается типом тернарного оператора будет наиболее общий тип его двух последних операндов. Что значит наиболее общий? Это легче всего пояснить на примерах. У int и short общим типом будет int.
У A и B в следующем фрагменте общим типом будет также int.

Т.е. наиболее общий тип это такой тип, к которому могу быть приведены оба операнда. Вполне могут быть ситуации, когда общего типа нет. Например у

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

Так. С типом тернарного оператора мы немного разобрались. Осталось решить вопрос с value category. Тут действует следующее правило: если в тернарном операторе происходит преобразование типов к наиболее общему, то тернарный оператор — rvalue. Если же нет, то lvalue. Теперь когда мы знаем то, что мы знаем, мы легко ответим на первые 7 вопросов.

Ответы

Как нам уже известно, второй и третий операнд тернарного оператора приводятся к наиболее общему типу. В данном случае это const char*. Но объект String(«dcba») уничтожится в конце выражения и s будет указывать на невалидную память. В лучшем случае программа упадет при попытке в дальнейшем использовать s. В худшем будет выдавать неверные результаты, вызывая недовольство у заказчика и головную боль у программиста.

«Необычное» использование тернарного оператора

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *