C # Условный оператор не оператор? - PullRequest
22 голосов
/ 06 апреля 2010

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

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

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

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

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

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

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

Ответы [ 9 ]

19 голосов
/ 06 апреля 2010

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

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

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

16 голосов
/ 06 апреля 2010

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

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

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

7 голосов
/ 06 апреля 2010

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

HashSet<long> groupUIDs = new HashSet<long>();
int count = groupUIDs.Add(uid)? unique++ : dupes++;
5 голосов
/ 06 апреля 2010

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

"something that is not a statement";

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

4 голосов
/ 06 апреля 2010

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

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

2 голосов
/ 06 апреля 2010

Для чего-то нужно использовать значение из троичного оператора ...

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++;
1 голос
/ 06 апреля 2010

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

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

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

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

1 голос
/ 06 апреля 2010

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

1 + 1;

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

0 голосов
/ 06 апреля 2010

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

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