Odpowiednik iif w C #

79

Czy istnieje IIfodpowiednik w C #? Lub podobny skrót?

Saif Khan
źródło
4
Myślę, że miałeś na myśli „skrót”, a nie „zwarcie” (co ma szczególne znaczenie w odniesieniu do operatorów logicznych) - czy mam rację?
Blorgbeard wychodzi

Odpowiedzi:

120

C # ma ?operator trójskładnikowy, podobnie jak inne języki w stylu C. Jednak nie jest to całkowicie równoważne z IIf(); istnieją dwie ważne różnice.

Aby wyjaśnić pierwszą różnicę, argument części fałszywej dla tego IIf()wywołania powoduje a DivideByZeroException, mimo że argumentem logicznym jest True.

IIf(true, 1, 1/0)

IIf()jest tylko funkcją i tak jak wszystkie inne funkcje, wszystkie argumenty muszą zostać ocenione przed wywołaniem. Innymi słowy, IIf()czy nie ma zwarcia w tradycyjnym sensie. Z drugiej strony to trójskładnikowe wyrażenie powoduje zwarcie, więc jest całkowicie w porządku:

(true)?1:1/0;

Inna różnica IIf()nie jest bezpieczna dla typu. Przyjmuje i zwraca argumenty typu Object. Operator trójskładnikowy jest bezpieczny dla typów. Używa wnioskowania o typie, aby wiedzieć, z jakimi typami ma do czynienia. Zauważ, że możesz to bardzo łatwo naprawić za pomocą własnej ogólnej IIF(Of T)()implementacji, ale po wyjęciu z pudełka tak nie jest.

Jeśli naprawdę chcesz IIf()w C #, możesz to mieć:

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

lub implementacja ogólna / bezpieczna dla typu:

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

Z drugiej strony, jeśli chcesz mieć operator trójskładnikowy w języku VB, program Visual Studio 2008 i nowsze wersje zapewniają nowy If() operator, który działa jak operator trójskładnikowy języka C #. Używa wnioskowania o typie, aby wiedzieć, co zwraca, i tak naprawdę jest operatorem, a nie funkcją. Oznacza to, że nie ma problemów z wstępną oceną wyrażeń, mimo że ma semantykę funkcji.

Joel Coehoorn
źródło
2
VB9 obsługuje prawdziwy operator trójskładnikowy. If (SomeBool, MessageBox.Show ("True"), MessageBox.Show ("False")) Jak widać tutaj: community.bartdesmet.net/blogs/bart/archive/2007/08/31/…
snarf
1
Wspominam o tym w ostatnim akapicie, ale pytanie dotyczyło konkretnie IIf ().
Joel Coehoorn
61

VB.NET:

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

DO#

someBool ? "true" : "false";
Kevin Pang
źródło
1
Chociaż dotyczy to prostych wyrażeń, te dwie formy nie są dokładnie równoważne, jeśli w wyrażeniach alternatywnych występują skutki uboczne. Iif (t, foo (), bar ()) wywoła zarówno foo (), jak i bar (), podczas gdy t? foo (): bar () wywoła tylko foo () lub bar (), ale nie oba. Więcej informacji można znaleźć w odpowiedzi Joela Coehoorna na to pytanie.
Greg Hewgill
1
Zaktualizowana odpowiedź, aby użyć funkcji „If” VB.NET zamiast „IIf”, tak aby dwa bloki kodu były równoważne.
Kevin Pang
13

operator trójskładnikowy

bool a = true;

string b = a ? "if_true" : "if_false";
Ris Adams
źródło
dodałbym tam komentarz, że to ciąg b = (a? "asdf": "dsrs"); tzn. wtedy można lepiej zrozumieć, jak to działa i zobaczyć, że nie jest to coś naprawdę dziwnego i bezsensownego, jak (ciąg b = a)? „sdf”: „sdsdf”).
barlop
10

Przydatny jest także operator łączenia ??:

VB:

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

DO#:

return s ?? "My Default Value";
John Gibb
źródło
1

To operator trójskładnikowy ?

string newString = i == 1 ? "i is one" : "i is not one";
Jon Limjap
źródło
0

Jest ograniczona w tym, że nie możesz tam umieszczać oświadczeń. Możesz umieścić tylko wartości (lub rzeczy, które zwracają / oceniają wartości), aby zwrócić

To działa („a” to statyczna liczba int w klasie Blah)

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

(nawiasy okrągłe znajdują się niedokładnie między równymi a znakiem zapytania).

To nie działa.

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

Dlatego do zwracania wartości można używać tylko operatora trójargumentowego języka C #. Nie jest to więc skrócona forma if. Javascript i być może niektóre inne języki pozwalają na umieszczanie tam instrukcji.

barlop
źródło
Tak, ponieważ ustawia wartość, a nie wywołuje metodę. Możesz jednak Actionrobić, co chcesz.
Kieran Foot
@KieranFoot WriteLine to metoda. Minęło trochę czasu, ale jeśli iiflub operator trójskładnikowy, pozwólcie wstawić tam wartość zwracaną, tak jak Blah.a = Blah.a < 4 ? Console.WriteLine("asdf"); return 1: Console.WriteLine("34er") ; return 2; wtedy, gdyby na to pozwalał, zadziałałoby, ale najwyraźniej nie. I tak, wciąż ustawia wartość i nie, nie wywołuje tam żadnej nowej metody.
barlop