Różnica w wydajności między IIf () i If

98

Czy w języku Visual Basic występuje różnica w wydajności w przypadku używania IIffunkcji zamiast Ifinstrukcji?

Bryan Roth
źródło

Odpowiedzi:

140

VB ma następujące Ifstwierdzenie, do którego, jak sądzę, odnosi się pytanie:

' Usage 1
Dim result = If(a > 5, "World", "Hello")
' Usage 2
Dim foo = If(result, "Alternative")

Pierwszy to w zasadzie trójskładnikowy operator warunkowy w języku C #, a drugi to jego operator łączenia (zwrot, resultchyba że jest Nothing, w takim przypadku powrót "Alternative"). Ifw ten sposób zastąpił, IIfa ten ostatni jest przestarzały.

Podobnie jak w C #, warunkowe Ifzwarcia operatora VB , więc możesz teraz bezpiecznie napisać co następuje, co nie jest możliwe przy użyciu IIffunkcji:

Dim len = If(text Is Nothing, 0, text.Length)
Konrad Rudolph
źródło
2
Nie odpowiedziałeś na pytanie dotyczące wydajności, a także nie wspomniałeś o skutkach ubocznych IIf.
jor
2
@jor Ostatni akapit mojej odpowiedzi dotyczy skutków ubocznych. Wydajność nie ma większego znaczenia, gdy jedna z opcji jest przestarzała. Bez względu na to, natywny operator Ifjest znacznie wydajniejszy niż IIffunkcja.
Konrad Rudolph
2
@mmcrae Zgadza się i celowo: jak powiedziałem, IIf jest przestarzały, więc nie ma sensu o tym dyskutować. To powiedziawszy, mój ostatni akapit omawia istotną różnicę. To wszystko, co musisz wiedzieć, naprawdę.
Konrad Rudolph
2
Doceniam, że chcesz wspierać dobre standardy i upewnić się, że nowicjusze nie dostrzegają złych praktyk, ale ktoś może mieć całkowicie uzasadniony problem, który spowodował, że chce lepiej zrozumieć różnicę ... Tak jak utrzymywanie starego kodu, utknięcie w jakieś inne narzędzie, które go wykorzystuje, itp. I That's all you need to know, reallynie brzmi jak sprzyjająca postawa dla strony poświęconej dzieleniu się wiedzą;)
Don Cheadle
1
@mmcrae Och, nie chciałem lekceważyć, po prostu naprawdę miałem na myśli, że wnętrze IIf jest nudno trywialne. Zawiera po prostu konwencjonalną instrukcję If, co oznacza, że ​​ostatni fragment kodu w mojej odpowiedzi nie zostałby uruchomiony.
Konrad Rudolph
65

IIf()uruchamia zarówno kod prawda, jak i fałsz. W przypadku prostych rzeczy, takich jak przypisanie numeryczne, nie jest to wielka sprawa. Ale w przypadku kodu, który wymaga jakiegokolwiek przetwarzania, marnujesz cykle uruchamiające niezgodny warunek i prawdopodobnie powodując efekty uboczne.

Ilustracja kodu:

Module Module1
    Sub Main()
        Dim test As Boolean = False
        Dim result As String = IIf(test, Foo(), Bar())
    End Sub

    Public Function Foo() As String
        Console.WriteLine("Foo!")
        Return "Foo"
    End Function

    Public Function Bar() As String
        Console.WriteLine("Bar!")
        Return "Bar"
    End Function
End Module

Wyjścia:

Foo!
Bar!
Thomas G. Mayfield
źródło
13

Kolejnym dużym problemem związanym z IIf jest to, że faktycznie wywoła on wszystkie funkcje, które znajdują się w argumentach [1], więc jeśli masz sytuację podobną do poniższej:

string results = IIf(Not oraData.IsDBNull(ndx), oraData.GetString(ndx), string.Empty)

W rzeczywistości zgłosi wyjątek, co nie jest sposobem, w jaki większość ludzi myśli, że funkcja działa, gdy ją widzą po raz pierwszy. Może to również prowadzić do bardzo trudnych do naprawienia błędów w aplikacji.

[1] Funkcja IIf - http://msdn.microsoft.com/en-us/library/27ydhh0d(VS.71).aspx

rjzii
źródło
Dlatego jeśli przyszedłem zastąpić stary IIF, miałem problemy z IIF, ale JEŚLI zaoszczędziłem dodając wiele linii kodu.
NiL
7

Lepiej używać If zamiast IIf, aby poprawnie używać mechanizmu wnioskowania o typie (Option Infer On)

W tym przykładzie słowa kluczowe są rozpoznawane jako ciąg, gdy używam If:

Dim Keywords = If(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)

W przeciwnym razie jest rozpoznawany jako obiekt:

Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
Larry
źródło
6

Według tego gościa , IIf może trwać do 6 razy dłużej niż If / Then. YMMV.

Greg Hurlman
źródło
1
W moich obliczeniach empirycznych (10000000 cykli) oszacowałem, że IIf jest około 12 razy wolniejsze!
Phantômaxx
6

Ponadto w tym przypadku czytelność powinna być prawdopodobnie bardziej preferowana niż wydajność. Nawet jeśli IIF byłby bardziej wydajny, jest po prostu mniej czytelny dla docelowych odbiorców (zakładam, że jeśli pracujesz w Visual Basic, chcesz, aby inni programiści mogli łatwo czytać twój kod, co jest największym dobrodziejstwem VB ... i co moim zdaniem jest stracone w przypadku pojęć takich jak IIF).

Ponadto „IIF jest funkcją, w przeciwieństwie do funkcji IF będącej częścią składni języków” ... co oznacza dla mnie, że rzeczywiście, jeśli byłoby szybsze ... gdyby nie nic innego, jak tylko to, że instrukcja If może być bezpośrednio sprowadzona do małego zestawu rozkazów, zamiast konieczności przechodzenia do innego miejsca w pamięci, aby wykonać logikę znalezioną we wspomnianej funkcji. Może to banalna różnica, ale warto ją zauważyć.

EdgarVerona
źródło
6

Uważam, że główna różnica między If i IIf to:

  • Jeśli (test [boolean], instrukcja1, instrukcja2) oznacza to, że zgodnie z wartością testu zostanie wykonana satement1 lub instrukcja2 (zostanie wykonana tylko jedna instrukcja)

  • Dim obj = IIF (test [boolean], instrukcja1, instrukcja2) oznacza to, że obie instrukcje zostaną wykonane, ale zgodnie z wartością testową jedna z nich zwróci wartość do (obj).

więc jeśli jedna z instrukcji zgłosi wyjątek, i tak wyrzuci ją w (IIf), ale w (If) wyrzuci ją na wypadek, gdyby warunek zwrócił jego wartość.

jakiś facet
źródło
5

... dlaczego może to potrwać tak długo, jak 6x, powiedz wiki:

Ponieważ IIf jest funkcją biblioteczną, zawsze będzie wymagać narzutu wywołania funkcji, podczas gdy operator warunkowy z większym prawdopodobieństwem utworzy kod wbudowany.

Zasadniczo IIf jest odpowiednikiem operatora trójskładnikowego w C ++ / C #, więc daje ci kilka ładnych instrukcji typu if / else, jeśli chcesz. Możesz również nadać mu funkcję oceny, jeśli chcesz.

Dillie-O
źródło
1

Te funkcje są różne! Być może wystarczy użyć instrukcji IF. Funkcja IIF zawsze będzie wolniejsza, ponieważ będzie wykonywać obie funkcje, a ponadto wykona standardową instrukcję IF.

Jeśli zastanawiasz się, dlaczego istnieje funkcja IIF, może to będzie wyjaśnienie:

Sub main()
    counter = 0
    bln = True
    s = iif(bln, f1, f2)
End Sub

Function f1 As String
    counter = counter + 1
    Return "YES"
End Function

Function f2 As String
    counter = counter + 1
    Return "NO"
End Function

Tak więc licznik po tym będzie wynosił 2, ale s będzie tylko „TAK”. Wiem, że ten licznik jest bezużyteczny, ale czasami są funkcje, które będziesz potrzebować do uruchomienia obu, nie ma znaczenia, czy to prawda, czy fałsz, i po prostu przypisz wartość jednej z nich do swojej zmiennej.

titol
źródło
jeśli potrzebujesz obu do uruchomienia, powinieneś jawnie wywołać je oba, a następnie wykonać standardowe If. Używanie IIf()w ten sposób zmyli ludzi czytających Twój kod.
Spivonious
Wiem o tym, ale pytanie dotyczy różnicy między tymi dwoma.
titol
Nie chciałem, aby komentarz odebrał jako krytykę; Zwróciłem tylko uwagę, że używanie go w ten sposób nie jest dobrą praktyką.
Spivonious