Ассоциативность троичных операторов в C # - могу ли я на это положиться?

StackOverflow https://stackoverflow.com/questions/1763543

Вопрос

Ах, разве тебе просто не нравятся хорошие троичные оскорбления?:) Рассмотрим следующее выражение:

true ? true : true ? false : false

Для тех из вас, кто сейчас совершенно сбит с толку, я могу сказать вам, что это оценивается как верно.Другими словами, это эквивалентно следующему:

true ? true : (true ? false : false)

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

(true ? true : true) ? false : false

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

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

obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)

Ясно и лаконично.Но это зависит от ассоциативности троичного оператора, работающего так же, как в первом случае.Скобки просто сделали бы из этого спагетти.

Итак, это где-нибудь указано?Я не смог его найти.

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

Решение

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

Соответствующий раздел в ECMA-334 (стандарт C #) - 14.13 §3:

Условный оператор является правоассоциативным, что означает, что операции группируются справа налево.[Пример:Выражение формы a ? b : c ? d : e оценивается как a ? b : (c ? d : e).конец пример]

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

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

Ре: «Попробуйте написать все В круглых скобках».

result = (obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
         (obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
         (obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
                                     obj1.Prop4.CompareTo(obj2.Prop4))))

Уточнение:

  • "Если ты надо спросить, не надо».
  • «Каждый, кто читает твой код..."

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

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

Тем не менее, если использование троичных выражений без круглых скобок является общепринятым и принятым соглашением в вашем проекте, обязательно используйте его! То, что вам пришлось спросить, указывает на то, что это не распространено и не принято в вашем проекте. Если вы хотите изменить соглашения в своем проекте, сделайте очевидно однозначные действия, отметьте это как нечто, что можно обсудить с другими участниками проекта, и двигайтесь дальше.Здесь это означает использование круглых скобок или использование if-else.

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

Отладка в два раза сложнее, чем написание кода.Поэтому, если вы пишете код максимально умно, вы по определению недостаточно умны, чтобы его отладить.— Брайан В.Керниган

Утверждение о том, что круглые скобки ухудшают читаемость кода, является ложным предположением.Я нахожу выражение в скобках гораздо более ясным.Лично я бы использовал круглые скобки и/или переформатировал несколько строк, чтобы улучшить читабельность.Переформатирование нескольких строк и использование отступов может даже устранить необходимость в скобках.И да, вы можете положиться на тот факт, что порядок ассоциации детерминирован, справа налево.Это позволяет выражению вычисляться слева направо ожидаемым образом.

obj1.Prop1 != obj2.Prop1
     ? obj1.Prop1.CompareTo(obj2.Prop1)
     : obj1.Prop2 != obj2.Prop2
           ? obj1.Prop2.CompareTo(obj2.Prop2)
           : obj1.Prop3 != obj2.Prop3
                  ? obj1.Prop3.CompareTo(obj2.Prop3)
                  : obj1.Prop4.CompareTo(obj2.Prop4);

Обратитесь к MSDN:http://msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx

«Если условие истинно, первое выражение вычисляется и становится результатом;если false, второе выражение оценивается и становится результатом.Всегда оценивается только одно из двух выражений».

x = cond1 ? result1
  : cond2 ? result2
  : cond3 ? result3
  : defaultResult;

против

if (cond1) x = result1;
else if (cond2) x = result2;
else if (cond3) x = result3;
else x = defaultResult;

Мне нравится первый.

Да, вы можете положиться на условную ассоциативность операторов.В руководстве по ссылке, любезно предоставленной dcp, указано как «Условный оператор правоассоциативный», с примером.И, как вы предположили, и я и другие согласились, тот факт, что на него можно положиться, позволяет сделать код более понятным.

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