Вопрос по c#, conditional-operator – C # Условный оператор не оператор?

22

У меня есть небольшой фрагмент кода, который меня расстраивает:

HashSet<long> groupUIDs = new HashSet<long>();
groupUIDs.Add(uid)? unique++ : dupes++;

Во время компиляции выдает ошибку:

Только операторы присваивания, вызова, приращения, декремента и нового объекта могут использоваться в качестве оператора

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

Когда я переформатирую его как если-то-иначе, он работает нормально.

Может кто-нибудь объяснить ошибку, и если есть способ сделать это в виде простого троичного оператора?

Вместо этого я предпочитаю if statemnet. Фиктивная переменная присваивания, которую предлагают некоторые ответы, только добавляет путаницы. bruno conde
Также обратите внимание, что тройки обычно используются для выбора значения, а не для выбора действия. В вашем случае вы выбираете, увеличивать ли одно из двух значений. Таким образом, имеет смысл в семантическом смысле использовать if-else, поскольку вы выбираете действие. AaronLS

Ваш Ответ

9   ответов
1

описание троичного оператора в ссылке на язык говорит, что

Если условие истинно, первое выражение вычисляется и становится результатом; если false, второе выражение оценивается и становится результатом.

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

На мой взгляд, переписывание как if / else было бы более понятным.

Вы правы - я спешил, и моя формулировка была слишком свободной. Andy Johnson
Это не должно быть присваивание - вы можете передать его другому методу, например. Jon Skeet
5

он не может быть использован в инструкции один - это эквивалент написания

"something that is not a statement";

Чтобы уточнить, вы должны вынуть троичный оператор и использовать if.

Это отличное объяснение, потому что если вы думаете о том, как работает троичный, он оценивает одно значение, значение, которое выбирается из двух вариантов. Таким образом, после оценки это похоже на написание утверждения, которое является значениемunique; (после увеличения) илиdupes; что-то вроде12345; который не был бы действительным утверждением, так как это всего лишь целое число. AaronLS
По крайней мере, в C и C ++ это вполне допустимое (хотя и без побочных эффектов) утверждение. Видимо, это не так в C #. Оказывается, правильный ответ - иметь фиктивное назначение, как предложено @sth. abelenky
@AaronLS: Во-первых, это будет значение уникального ПРИОР для увеличения, а не после. Во-вторых, во многих языках наличие единственного целого числа вполне допустимо. C # отличается в этом отношении. abelenky
@abelenky Хороший вызов по порядку работы, я подумал о постфиксе, но действительно сосредоточился на том факте, что он вычисляется как целое число. Мы могли бы исследовать все различные способы, которыми разные языки справились бы с этим, например, «12345» не является полным утверждением на английском языке, но поскольку вопрос помечен как C #, я думаю, что было бы полезно сосредоточиться на этом;) AaronLS
Кстати, я понятия не имел, что одиночные целые могут быть операторами на других языках - и я знаю несколько. Один продолжает учиться. :) ANeves
19

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

int dummy = groupUIDs.Add(uid)? unique++ : dupes++;

При этом я бы рекомендовал просто использовать if-then-else. Это менее запутанно, потому что не требует создания "магических" фиктивных переменных ...

Это, кажется, исправить это. В Си нет ничего плохого в автономном троичном, который ничего не делает. Видимо, это не так в C #. Благодарю. abelenky
@abelenky - Я определенно понимаю, почему ты не назначил это ни на что, но в C # ты должен, я бы хотел, чтобы ты этого не делал, своего рода пустая трата времени. У меня была та же самая проблема несколько лет назад, и это действительно смутило меня ... Я не считаю это фиктивной ошибкой или чем-то еще. Gabe
Или используйте вместо тернарного оператора if вместо присвоения значения бесполезной переменной ради крутости кода и ухудшения читаемости. ANeves
Я предпочитаю открывающие скобки в одной строке, но вы абсолютно правы относительно количества строк. Во что бы то ни стало используйте троичный оп и манекен, если это ваше предпочтение - если это выбор из знания, это хороший выбор. :) ANeves
2

HashSet<long> groupUIDs = new HashSet<long>();
int newCount = groupUIDs.Add(uid)? unique++ : dupes++;

или - используйте if

HashSet<long> groupUIDs = new HashSet<long>();
if (groupUIDs.Add(uid))
   unique++;
else
   dupes++;
0

почему ваша линия будет? Просто используйте оператор if :-)

        bool b = false;
        b?callB():callA();
7

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

HashSet<long> groupUIDs = new HashSet<long>();
int count = groupUIDs.Add(uid)? unique++ : dupes++;
16

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

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

У вас есть побочный эффект, поэтому используйте условное выражение, а не условное выражение.

@abelenky: Я польщен, но, пожалуйста, не делай это ради меня. Делайте это ради будущих людей, которые должны поддерживать ваш код. :-) Eric Lippert
Из уважения к @EricLippert, я заменю его на условный оператор, если-еще. Еще один шаг вверх по кривой обучения от C до C #. abelenky
1

троичный оператор предназначен для того, чтобы дать вам результат, так же, как1 + 1 дает тебе2, Вы не могли бы просто написать:

1 + 1;

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

4

Add он жалуется на то, что ваше условное выражение не является полным утверждением.

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

@abelenky: нет ничего плохого в использовании++ оператор здесь. Проблема в том, что само троичное выражение не является утверждением: что-то вродеgroupUIDs.Add(uid) ? 0 : 1; тоже не сработает. LukeH
На самом деле, это жалуется на троичного оператора. Mehrdad Afshari
@Andrew Разве это не будет считаться приращением, которое упоминается в сообщении об ошибке как допустимое утверждение? AaronLS
@Merhdad - Да, вы правы - я исправляю это сейчас. Andrew Hare

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