Если эквивалентно в C#

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


person Saif Khan    schedule 05.05.2009    source источник
comment
Я думаю, вы имели в виду короткое замыкание, а не короткое замыкание (которое имеет особое значение в отношении логических операторов) - я прав?   -  person Blorgbeard    schedule 05.05.2009


Ответы (7)


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

Чтобы объяснить первое различие, аргумент ложной части для этого вызова IIf() вызывает 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#. Он использует определение типа, чтобы узнать, что он возвращает, и на самом деле это оператор, а не функция. Это означает, что нет никаких проблем с предварительной оценкой выражений, даже несмотря на то, что у них есть семантика функций.

person Joel Coehoorn    schedule 05.05.2009
comment
VB9 поддерживает настоящий тернарный оператор. If(SomeBool, MessageBox.Show(True), MessageBox.Show(False)) Как показано здесь: community.bartdesmet.net/blogs/bart/archive/2007/08/31/ - person snarf; 05.05.2009
comment
Я упоминал об этом в последнем абзаце, но вопрос был конкретно о IIf(). - person Joel Coehoorn; 05.05.2009

ВБ.NET:

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

C#

someBool ? "true" : "false";
person Kevin Pang    schedule 05.05.2009
comment
Хотя это верно для простых выражений, эти две формы не совсем эквивалентны, если в альтернативных выражениях есть побочные эффекты. Iif(t, foo(), bar()) вызовет как foo(), так и bar(), а t ? foo() : bar() будет вызывать либо foo(), либо bar(), но не оба. См. ответ Джоэла Коегоорна на этот вопрос для получения дополнительной информации. - person Greg Hewgill; 05.05.2009
comment
Обновлен ответ для использования функции VB.NET If вместо IIf, чтобы два блока кода были эквивалентны. - person Kevin Pang; 07.06.2011

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

bool a = true;

string b = a ? "if_true" : "if_false";
person Ris Adams    schedule 05.05.2009
comment
я бы добавил туда комментарий, что это строка b= (a ? asdf : dsrs); то есть тогда можно лучше понять, как это работает, и увидеть, что это не что-то действительно странное и бессмысленное вроде (string b=a) ? сдф: сдсдф). - person barlop; 20.04.2016

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

VB:

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

C#:

return s ?? "My Default Value";
person John Gibb    schedule 05.05.2009

booleanExpression ? trueValue : falseValue;

Пример:

string itemText = count > 1 ? "items" : "item";

http://zamirsblog.blogspot.com/2011/12/c-vb-equivalent-of-iif.html

person Zamir    schedule 08.12.2011

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

string newString = i == 1 ? "i is one" : "i is not one";
person Jon Limjap    schedule 05.05.2009

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

Это работает ('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");

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

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