Эквивалент Iif в C #

79

Есть ли IIfэквивалент в C #? Или аналогичный ярлык?

Саиф Хан
источник
4
Я думаю, вы имели в виду «короткий путь», а не «короткое замыкание» (что имеет особое значение в отношении логических операторов) - я прав?
Blorgbeard выйдет

Ответы:

120

В C # ?, как и в других языках C-стиля, есть тернарный оператор. Однако это не полностью эквивалентно IIf(); есть два важных отличия.

Чтобы объяснить первое отличие, аргумент ложной части для этого IIf()вызова вызывает a DivideByZeroException, хотя логический аргумент имеет значение True.

IIf(true, 1, 1/0)

IIf()- это просто функция, и, как и все функции, все аргументы должны быть оценены перед вызовом. Иными словами, IIf()делает не короткое замыкание в традиционном смысле этого слова. С другой стороны, в этом троичном выражении происходит короткое замыкание, и поэтому все в порядке:

(true)?1:1/0;

Другое отличие IIf()- небезопасный тип. Он принимает и возвращает аргументы типа Object. Тройной оператор является тип безопасности. Он использует вывод типов, чтобы знать, с какими типами имеет дело. Обратите внимание, что вы можете очень легко исправить это с помощью своей собственной общей IIF(Of T)()реализации, но из коробки это не так.

Если вы действительно хотите использовать IIf()C #, вы можете получить его:

object IIf(bool expression, object truePart, object falsePart) 
{return expression?truePart:falsePart;}

или универсальная / типобезопасная реализация:

T IIf<T>(bool expression, T truePart, T falsePart) 
{return expression?truePart:falsePart;}

С другой стороны, если вы хотите, чтобы тернарный оператор в VB, Visual Studio 2008 и более поздних версий предоставил новый If() оператор, который работает как тернарный оператор C #. Он использует вывод типа, чтобы узнать, что он возвращает, и на самом деле это оператор, а не функция. Это означает, что нет проблем с предварительной оценкой выражений, даже если они имеют семантику функций.

Джоэл Кохорн
источник
2
VB9 поддерживает истинный тернарный оператор. Если (SomeBool, MessageBox.Show ("True"), MessageBox.Show ("False")) Как видно здесь: community.bartdesmet.net/blogs/bart/archive/2007/08/31/…
snarf
1
Я упоминал об этом в последнем абзаце, но вопрос касался именно IIf ().
Джоэл Кохорн
61

VB.NET:

If(someBool, "true", "false")

C #

someBool ? "true" : "false";
Кевин Панг
источник
1
Хотя это верно для простых выражений, эти две формы не совсем эквивалентны, если в альтернативных выражениях есть побочные эффекты. Iif (t, foo (), bar ()) будет вызывать как foo (), так и bar (), а t? foo (): bar () будет вызывать только либо foo (), либо bar (), но не оба сразу. См. Ответ Джоэла Кохорна на этот вопрос для получения дополнительной информации.
Грег Хьюгилл
1
Обновлен ответ на использование функции «If» VB.NET вместо «IIf», чтобы два блока кода были эквивалентны.
Кевин Пан,
13

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

bool a = true;

string b = a ? "if_true" : "if_false";
Рис Адамс
источник
я бы добавил туда комментарий, что строка b = (a? "asdf": "dsrs"); т.е. тогда можно лучше понять, как это работает, и увидеть, что это не что-то действительно странное и бессмысленное, например (строка b = a)? "sdf": "sdsdf").
barlop
10

Также полезен оператор объединения ??:

VB:

Return Iif( s IsNot Nothing, s, "My Default Value" )

C #:

return s ?? "My Default Value";
Джон Гибб
источник
1

Это тернарный оператор ?

string newString = i == 1 ? "i is one" : "i is not one";
Джон Лимджап
источник
0

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

Это работает ('a' - статический int в классе Blah)

Blah.a=Blah.a<5?1:8;

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

Это не работает.

Blah.a = Blah.a < 4 ? Console.WriteLine("asdf") : Console.WriteLine("34er");
or
Blah.a = Blah.a < 4 ? MessageBox.Show("asdf") : MessageBox.Show("34er");

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

барлоп
источник
Да, потому что он устанавливает значение, а не вызывает метод. Однако вы можете Actionделать то, что хотите.
Kieran Foot
@KieranFoot WriteLine - это метод. Прошло некоторое время, но If iifили тернарный оператор, позвольте вам поместить туда возвращаемое значение, например, Blah.a = Blah.a < 4 ? Console.WriteLine("asdf"); return 1: Console.WriteLine("34er") ; return 2; если бы он это позволял, это сработало бы, но, по-видимому, это не так. И да, он все еще устанавливает значение и не вызывает там никаких новых методов.
barlop