¿Existe un equivalente de VB.NET para C # 's' ?? ' ¿operador?

180

¿Existe un equivalente de VB.NET para el ??operador de C # ?

Nathan Koop
fuente
44
La mayoría de las respuestas aquí (incluida la respuesta aceptada) no son correctas y no son funcionalmente equivalentes a ?? en todas las situaciones El equivalente correcto es la declaración if () con 2 argumentos. Sin embargo, el segundo argumento se puede anidar para lograr exactamente los mismos resultados que ?? con múltiples argumentos
user1751825
¿Se refiere al operador ternario?: Por ejemplo, return ((valor <0)? Verdadero: falso)
Zeek2

Respuestas:

155

Use el If()operador con dos argumentos ( documentación de Microsoft ):

' Variable first is a nullable type.
Dim first? As Integer = 3
Dim second As Integer = 6

' Variable first <> Nothing, so its value, 3, is returned.
Console.WriteLine(If(first, second))

second = Nothing
' Variable first <> Nothing, so the value of first is returned again. 
Console.WriteLine(If(first, second))

first = Nothing second = 6
' Variable first = Nothing, so 6 is returned.
Console.WriteLine(If(first, second))
Firas Assaad
fuente
3
Creo que la If()declaración en VB es la misma que if...?...:en C #, no el ??operador
Luke T O'Brien
2
@ LukeTO'Brien Eso es si lo usas con 3 argumentos. Si lo usa con 2 argumentos, es más que eso ??(vea otra respuesta a esta pregunta: stackoverflow.com/a/20686360/1474939 )
Brian J
2
Esta respuesta muestra cómo usar VB If con tres parámetros . Eso no es similar al ??operador de C # . La mejor respuesta es If de Code Maverick con dos argumentos . (Nick tuvo una respuesta similar, años antes, pero no incluye la explicación de MSDN.)
ToolmakerSteve
1
Esto responde a una pregunta completamente diferente.
Marc Gravell
1
Para comprender los comentarios anteriores, mira el historial de edición.
Zev Spitz
70

La respuesta aceptada no tiene ninguna explicación y es simplemente un enlace.
Por lo tanto, pensé en dejar una respuesta que explica cómo funciona el Ifoperador tomado de MSDN:


Operador If (Visual Basic)

Utiliza la evaluación de cortocircuito para devolver condicionalmente uno de los dos valores. El operador If se puede llamar con tres argumentos o con dos argumentos.

If( [argument1,] argument2, argument3 )


Si el operador fue llamado con dos argumentos

El primer argumento para If se puede omitir. Esto permite que se llame al operador utilizando solo dos argumentos. La siguiente lista se aplica solo cuando se llama al operador If con dos argumentos.


Partes

Term         Definition
----         ----------

argument2    Required. Object. Must be a reference or nullable type. 
             Evaluated and returned when it evaluates to anything 
             other than Nothing.

argument3    Required. Object.
             Evaluated and returned if argument2 evaluates to Nothing.


Cuando se omite el argumento booleano , el primer argumento debe ser una referencia o un tipo anulable. Si el primer argumento se evalúa como Nothing , se devuelve el valor del segundo argumento. En todos los demás casos, se devuelve el valor del primer argumento. El siguiente ejemplo ilustra cómo funciona esta evaluación.


VB

' Variable first is a nullable type. 
Dim first? As Integer = 3
Dim second As Integer = 6

' Variable first <> Nothing, so its value, 3, is returned.
Console.WriteLine(If(first, second))

second = Nothing 
' Variable first <> Nothing, so the value of first is returned again.
Console.WriteLine(If(first, second))

first = Nothing
second = 6
' Variable first = Nothing, so 6 is returned.
Console.WriteLine(If(first, second))

Un ejemplo de cómo manejar más de dos valores ( ifs anidados ):

Dim first? As Integer = Nothing
Dim second? As Integer = Nothing
Dim third? As Integer = 6
' The LAST parameter doesn't have to be nullable.
'Alternative: Dim third As Integer = 6

' Writes "6", because the first two values are "Nothing".
Console.WriteLine(If(first, If(second, third)))
Code Maverick
fuente
18

Puedes usar un método de extensión. Este funciona como SQL COALESCEy probablemente sea excesivo para lo que está tratando de probar, pero funciona.

    ''' <summary>
    ''' Returns the first non-null T based on a collection of the root object and the args.
    ''' </summary>
    ''' <param name="obj"></param>
    ''' <param name="args"></param>
    ''' <returns></returns>
    ''' <remarks>Usage
    ''' Dim val as String = "MyVal"
    ''' Dim result as String = val.Coalesce(String.Empty)
    ''' *** returns "MyVal"
    '''
    ''' val = Nothing
    ''' result = val.Coalesce(String.Empty, "MyVal", "YourVal")
    ''' *** returns String.Empty
    '''
    ''' </remarks>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function Coalesce(Of T)(ByVal obj As T, ByVal ParamArray args() As T) As T

        If obj IsNot Nothing Then
            Return obj
        End If

        Dim arg As T
        For Each arg In args
            If arg IsNot Nothing Then
                Return arg
            End If
        Next

        Return Nothing

    End Function

El incorporado If(nullable, secondChoice)solo puede manejar dos opciones anulables. Aquí, uno puede Coalescetantos parámetros como desee. Se devolverá el primer no nulo, y el resto de los parámetros no se evaluarán después de eso (cortocircuito, como AndAlso/ &&y OrElse/ ||)

StingyJack
fuente
8
Porque el lenguaje tiene un operador incorporado. No hay razón para mirar siquiera los métodos de extensión.
Nick
2
No voy a repetir la respuesta de otra persona. Pensé que sería bueno proporcionar una solución alternativa si necesita verificar varios valores con una sola declaración. Como no es una respuesta INCORRECTA, ¿debería ser rechazada?
StingyJack
1
+1 por proporcionar una implementación utilizando genéricos y evitar la conversión de tipos / boxing / unboxing
ulty4life
44
@ Nick, lo siento, pero simplemente estás equivocado. Si tiene más de dos argumentos de fusión, la función integrada no lo cortará.
toddmo
Podrías saltarte el obj param y dejar que el cuerpo sea Return args.FirstOrDefault(Function(arg) arg IsNot Nothing):-)
Ulf Åkerstedt
11

La única limitación importante de la mayoría de estas soluciones es que no cortocircuitarán. Por lo tanto, en realidad no son equivalentes a ??.

El Ifoperador incorporado no evaluará los parámetros posteriores a menos que el parámetro anterior no se evalúe como nada.

Las siguientes declaraciones son equivalentes:

C#

var value = expression1 ?? expression2 ?? expression3 ?? expression4;

VB

dim value = if(expression1,if(expression2,if(expression3,expression4)))

Esto funcionará en todos los casos donde ??funciona. Cualquiera de las otras soluciones debería usarse con extrema precaución, ya que podrían introducir fácilmente errores de tiempo de ejecución.

usuario1751825
fuente
Esto no funciona en casos donde hay un número desconocido de parámetros (bueno ... no sin usar roslyn o codedom para precompilar una declaración para que coincida con el número de parámetros en ese momento de la ejecución).
StingyJack
@StingyJack No está destinado a hacerlo. Hace exactamente lo que el ?? operador hace.
user1751825
2

Consulte la documentación de Microsoft sobre If Operator (Visual Basic) aquí: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/if-operator

If( [argument1,] argument2, argument3 )

Aquí hay algunos ejemplos (VB.Net)

' This statement prints TruePart, because the first argument is true.
Console.WriteLine(If(True, "TruePart", "FalsePart"))

' This statement prints FalsePart, because the first argument is false.
Console.WriteLine(If(False, "TruePart", "FalsePart"))

Dim number = 3
' With number set to 3, this statement prints Positive.
Console.WriteLine(If(number >= 0, "Positive", "Negative"))

number = -1
' With number set to -1, this statement prints Negative.
Console.WriteLine(If(number >= 0, "Positive", "Negative"))
FN90
fuente
1
¡Agradable! Eliminando comentario!
Alec