Diferencia de rendimiento entre IIf () y If

Respuestas:

140

VB tiene la siguiente Ifdeclaración a la que se refiere la pregunta, creo:

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

El primero es básicamente el operador condicional ternario de C # y el segundo es su operador combinado (return a resultmenos que sea Nothing, en cuyo caso return "Alternative"). Ifha reemplazado IIfy este último es obsoleto.

Al igual que en C #, el Ifoperador condicional de VB se cortocircuita, por lo que ahora puede escribir con seguridad lo siguiente, lo que no es posible con la IIffunción:

Dim len = If(text Is Nothing, 0, text.Length)
Konrad Rudolph
fuente
2
No respondió la pregunta de rendimiento y tampoco mencionó los efectos secundarios de IIf.
jor
2
@jor El último párrafo de mi respuesta trata sobre los efectos secundarios. El rendimiento no es realmente relevante cuando una de las opciones está obsoleta. Por lo que vale, el operador nativo Ifes mucho más eficiente que la IIffunción.
Konrad Rudolph
2
@mmcrae Eso es correcto y a propósito: como he dicho, IIf es obsoleto, por lo que tiene poco sentido discutirlo. Dicho esto, mi último párrafo discute la diferencia relevante. Eso es todo lo que necesitas saber, de verdad.
Konrad Rudolph
2
Aprecio que quiera respaldar los buenos estándares y asegurarse de que los novatos no aprendan malas prácticas, pero alguien puede tener un problema perfectamente legítimo que les haya hecho querer comprender mejor la diferencia ... como mantener el código heredado, quedarse atascado alguna otra herramienta que lo use, etc. Y That's all you need to know, reallyno suena como una actitud propicia para un sitio web dedicado al intercambio de conocimientos;)
Don Cheadle
1
@mmcrae Oh, no quise ser despectivo, solo quise decir que las partes internas de IIf son aburridas y triviales. Simplemente contiene una declaración If convencional, lo que implica que la última pieza de código en mi respuesta no se ejecutaría.
Konrad Rudolph
65

IIf()ejecuta tanto el código verdadero como el falso. Para cosas simples como la asignación numérica, esto no es un gran problema. Pero para el código que requiere algún tipo de procesamiento, está desperdiciando ciclos ejecutando la condición que no coincide y posiblemente causando efectos secundarios.

Ilustración de código:

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

Salidas:

Foo!
Bar!
Thomas G. Mayfield
fuente
13

Además, otro gran problema con el IIf es que realmente llamará a cualquier función que esté en los argumentos [1], así que si tienes una situación como la siguiente:

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

En realidad, lanzará una excepción, que no es la forma en que la mayoría de la gente cree que funciona la función la primera vez que la ve. Esto también puede llevar a algunos errores muy difíciles de corregir en una aplicación.

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

rjzii
fuente
Es por eso que si venía a reemplazar el antiguo IIF, solía tener problemas con IIF pero si guardaba la adición de muchas líneas de código.
NiL
7

Es mejor usar If en lugar de IIf para usar el mecanismo de inferencia de tipos correctamente (Option Infer On)

En este ejemplo, las palabras clave se reconocen como una cadena cuando uso If:

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

De lo contrario, se reconoce como un objeto:

Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
Larry
fuente
6

Según este tipo , IIf puede tardar hasta 6 veces más que If / Then. YMMV.

Greg Hurlman
fuente
1
En mis cálculos empíricos (10000000 ciclos), ¡evalué que IIf era aproximadamente 12 veces más lento!
Phantômaxx
6

Además de eso, la legibilidad probablemente debería ser más preferida que el rendimiento en este caso. Incluso si IIF fuera más eficiente, simplemente es menos legible para el público objetivo (supongo que si está trabajando en Visual Basic, desea que otros programadores puedan leer su código fácilmente, que es la mayor ventaja de VB ... y que se pierde con conceptos como IIF en mi opinión).

Además, "IIF es una función, frente a SI es parte de la sintaxis de los lenguajes" ... lo que me implica que, de hecho, If sería más rápido ... si no fuera por otra cosa que la declaración If se puede resumir directamente a un pequeño conjunto de opcodes en lugar de tener que ir a otro espacio en la memoria para realizar la lógica encontrada en dicha función. Es una diferencia trivial, quizás, pero vale la pena señalarla.

EdgarVerona
fuente
6

Creo que la principal diferencia entre If y IIf es:

  • Si (prueba [booleano], sentencia1, sentencia2) significa que de acuerdo con el valor de prueba se ejecutará satement1 o sentencia2 (solo se ejecutará una sentencia)

  • Dim obj = IIF (test [boolean], statement1, statement2) significa que ambas sentencias se ejecutarán, pero de acuerdo con el valor de prueba, una de ellas devolverá un valor a (obj).

por lo que si una de las declaraciones arroja una excepción, la arrojará en (IIf) de todos modos, pero en (If) la arrojará en caso de que la condición devuelva su valor.

algún chico
fuente
5

... en cuanto a por qué puede tardar hasta 6 veces, dice la wiki:

Debido a que IIf es una función de biblioteca, siempre requerirá la sobrecarga de una llamada de función, mientras que un operador condicional probablemente producirá código en línea.

Básicamente, IIf es el equivalente de un operador ternario en C ++ / C #, por lo que le da algunas declaraciones de tipo if / else de 1 línea si lo desea. También puede darle una función para evaluar si lo desea.

Dillie-O
fuente
1

¡Esas funciones son diferentes! Quizás solo necesite usar la instrucción IF. IIF siempre será más lento, porque hará ambas funciones y además hará la instrucción IF estándar.

Si se pregunta por qué existe la función IIF, tal vez esta sea una explicación:

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

Entonces, el contador será 2 después de esto, pero s será solo "SÍ". Sé que estas cosas del contador son inútiles, pero a veces hay funciones que necesitará ambas para ejecutar, no importa si IF es verdadero o falso, y simplemente asigne el valor de uno de ellos a su variable.

titol
fuente
si necesita que se ejecuten ambos, debe llamarlos explícitamente a ambos y luego hacer un If estándar. Usarlo IIf()de esta manera solo confundirá a las personas que lean su código.
Spivonious
Lo sé, pero la pregunta es sobre la diferencia entre esos dos.
titol
No quise que el comentario pareciera una crítica; Solo estaba señalando que usarlo de esta manera no es una buena práctica.
Spivonious