Existe um equivalente em VB.NET para C # 's' ?? ' operador?

180

Existe um equivalente VB.NET para o ??operador de C # ?

Nathan Koop
fonte
4
A maioria das respostas aqui (incluindo a resposta aceita) não está correta e não é funcionalmente equivalente a ?? em todas as situações. O equivalente correto é a instrução if () com 2 argumentos. O segundo argumento, no entanto, pode ser aninhado para obter exatamente os mesmos resultados que ?? com vários argumentos.
User1751825
Você quer dizer o operador ternário: por exemplo retorno ((valor <0) true: false?)?
Zeek2

Respostas:

155

Use o If()operador com dois argumentos ( documentação da 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
fonte
3
Eu acho que a If()declaração em VB é o mesmo que o if...?...:em C #, não o ??operador
Luke T O'Brien
2
@ LukeTO'Brien Isso é se você usá-lo com 3 argumentos. Se você usá-lo com 2 argumentos, é mais que ??(ver outra resposta a esta pergunta: stackoverflow.com/a/20686360/1474939 )
Brian J
2
Esta resposta mostra como usar o VB If com três parâmetros . Isso não é semelhante ao ??operador do C # . Melhor resposta é If, do Code Maverick, com dois argumentos . (Nick teve uma resposta semelhante, anos antes, mas não inclui a explicação da MSDN.)
ToolmakerSteve
1
Isso responde a uma pergunta completamente diferente.
Marc Gravell
1
Para entender os comentários anteriores, consulte o histórico de edições.
Zev Spitz
70

A resposta aceita não tem nenhuma explicação e é apenas um link.
Portanto, pensei em deixar uma resposta que explique como o Ifoperador trabalha, retirado do MSDN:


Operador If (Visual Basic)

Utiliza a avaliação de curto-circuito para retornar condicionalmente um dos dois valores. O operador If pode ser chamado com três argumentos ou com dois argumentos.

If( [argument1,] argument2, argument3 )


Se o operador chamado com dois argumentos

O primeiro argumento para If pode ser omitido. Isso permite que o operador seja chamado usando apenas dois argumentos. A lista a seguir se aplica somente quando o operador If é chamado com dois argumentos.


Peças

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.


Quando o argumento booleano é omitido, o primeiro argumento deve ser um tipo de referência ou anulável. Se o primeiro argumento for avaliado como Nothing , o valor do segundo argumento será retornado. Em todos os outros casos, o valor do primeiro argumento é retornado. O exemplo a seguir ilustra como essa avaliação funciona.


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))

Um exemplo de como lidar com mais de dois valores ( ifs aninhados ):

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
fonte
18

Você pode usar um método de extensão. Este funciona como SQL COALESCEe provavelmente é um exagero para o que você está tentando testar, mas 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

O interno If(nullable, secondChoice)pode lidar apenas com duas opções anuláveis. Aqui, você pode Coalescequantos parâmetros desejar. O primeiro não nulo será retornado e o restante dos parâmetros não serão avaliados depois disso (curto-circuito, como AndAlso/ &&e OrElse/ ||)

StingyJack
fonte
8
Porque o idioma possui um operador interno. Não há razão para olhar para os métodos de extensão.
Nick
2
Não vou repetir a resposta de outra pessoa. Achei que seria bom fornecer uma solução alternativa se você precisar verificar vários valores com uma única instrução. Uma vez que não é uma resposta ERRADA, deve ser votada com voto negativo?
StingyJack 31/12/08
1
1 para fornecer uma implementação usando os genéricos e evitando tipo de fundição / boxing / unboxing
ulty4life
4
@ Nick, desculpe, mas você está simplesmente errado. Se você tiver mais de dois argumentos de coalescência, a função interna não a cortará.
toddmo
Você poderia pular o param obj e deixar o corpo ser Return args.FirstOrDefault(Function(arg) arg IsNot Nothing):-)
Ulf Åkerstedt
11

A única limitação significativa da maioria dessas soluções é que elas não causam um curto-circuito. Portanto, eles não são realmente equivalentes a ??.

O Ifoperador interno não avaliará os parâmetros subsequentes, a menos que o parâmetro anterior seja avaliado em nada.

As seguintes declarações são equivalentes:

C #

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

VB

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

Isso funcionará em todos os casos em que ??funciona. Qualquer uma das outras soluções teria que ser usada com extrema cautela, pois elas poderiam facilmente introduzir bugs em tempo de execução.

user1751825
fonte
Isso não funciona nos casos em que há um número desconhecido de parâmetros (bem ... não sem o uso de roslyn ou codedom para pré-compilar uma instrução para corresponder ao número de parâmetros naquele momento na execução).
precisa
@StingyJack Não se destina. Faz exatamente o que o ?? operador faz.
User1751825
2

Consulte a documentação da Microsoft sobre o If Operator (Visual Basic) aqui: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/if-operator

If( [argument1,] argument2, argument3 )

Aqui estão alguns exemplos (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
fonte
1
Agradável! Removendo comentário!
Alec