Czy istnieje odpowiednik VB.NET dla języka C #? operator?

180

Czy istnieje odpowiednik VB.NET dla ??operatora C # ?

Nathan Koop
źródło
4
Większość odpowiedzi tutaj (w tym odpowiedź zaakceptowana) jest nieprawidłowa i nie jest funkcjonalnie równoważna z ?? we wszystkich sytuacjach. Prawidłowym odpowiednikiem jest instrukcja if () z 2 argumentami. Drugi argument można jednak zagnieżdżać, aby uzyskać dokładnie takie same wyniki jak ?? z wieloma argumentami.
user1751825
Czy masz na myśli operatora trójskładnikowego?: Np. Return ((wartość <0)? True: false)
Zeek2 24.10.19

Odpowiedzi:

155

Użyj If()operatora z dwoma argumentami ( dokumentacja 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
źródło
3
Myślę, że If()instrukcja w VB jest taka sama jak if...?...:w C #, a nie ??operator
Luke T O'Brien
2
@ LukeTO'Brien To jest, jeśli używasz go z 3 argumentami. Jeśli użyjesz go z 2 argumentami, to więcej ??(zobacz inną odpowiedź na to pytanie: stackoverflow.com/a/20686360/1474939 )
Brian J
2
Ta odpowiedź pokazuje, jak używać VB If z trzema parametrami . To nie jest podobne do ??operatora C # . Lepszą odpowiedzią jest Code Maverick's If z dwoma argumentami . (Nick miał podobną odpowiedź wiele lat wcześniej, ale nie zawiera wyjaśnienia z MSDN.)
ToolmakerSteve
1
To odpowiada na zupełnie inne pytanie.
Marc Gravell
1
Aby zrozumieć poprzednie komentarze, spójrz na historię edycji.
Zev Spitz,
70

Akceptowana odpowiedź nie zawiera żadnego wyjaśnienia i jest po prostu linkiem.
Dlatego pomyślałem, że zostawię odpowiedź, która wyjaśnia, jak Ifdziała operator zaczerpnięty z MSDN:


Jeśli operator (Visual Basic)

Wykorzystuje ocenę zwarcia, aby warunkowo zwrócić jedną z dwóch wartości. Jeśli operator może być wywoływana z trzema argumentami lub z dwoma argumentami.

If( [argument1,] argument2, argument3 )


Jeśli operator zadzwonił z dwoma argumentami

Pierwszy argument argumentu If można pominąć. Umożliwia to wywoływanie operatora przy użyciu tylko dwóch argumentów. Poniższa lista ma zastosowanie tylko wtedy, gdy operator If jest wywoływany z dwoma argumentami.


Części

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.


Gdy argument boolowski zostanie pominięty, pierwszy argument musi być typem referencyjnym lub nullable. Jeśli pierwszy argument ma wartość Nic , zwracana jest wartość drugiego argumentu. We wszystkich innych przypadkach zwracana jest wartość pierwszego argumentu. Poniższy przykład ilustruje działanie tej oceny.


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

Przykład obsługi więcej niż dwóch wartości (zagnieżdżonych if):

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
źródło
18

Możesz użyć metody rozszerzenia. Ten działa jak SQL COALESCEi prawdopodobnie przesadza z tym, co próbujesz przetestować, ale działa.

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

Wbudowany If(nullable, secondChoice)może obsłużyć tylko dwa zerowane opcje. Tutaj można ustawić dowolną Coalesceliczbę parametrów. Pierwszy inny niż zerowy zostanie zwrócony, a pozostałe parametry nie zostaną następnie ocenione (zwarte, takie jak AndAlso/ &&i OrElse/ ||)

StingyJack
źródło
8
Ponieważ język ma wbudowany operator. Nie ma powodu, aby nawet patrzeć na metody rozszerzenia.
Nick
2
Nie zamierzam powtarzać odpowiedzi innej osoby. Uznałem, że fajnie byłoby podać alternatywne rozwiązanie, jeśli chcesz sprawdzić wiele wartości za pomocą jednej instrukcji. Skoro nie jest to ZŁA odpowiedź, to czy należy ją zanotować?
StingyJack
1
+1 za zapewnienie implementacji przy użyciu ogólnych i unikanie rzutowania / boksowania / rozpakowywania
ulty4life
4
@Nick, przepraszam, ale po prostu się mylisz. Jeśli masz więcej niż dwa argumenty koalescencji, wbudowana funkcja tego nie wycina.
toddmo
Możesz pominąć obj param i pozwolić ciału być Return args.FirstOrDefault(Function(arg) arg IsNot Nothing):-)
Ulf Åkerstedt
11

Jedynym znaczącym ograniczeniem większości tych rozwiązań jest to, że nie powodują zwarcia. Dlatego nie są w rzeczywistości równoważne z ??.

Wbudowany Ifoperator nie oceni kolejnych parametrów, chyba że wcześniejszy parametr nie da wartości.

Następujące instrukcje są równoważne:

DO#

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

VB

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

??Działa to we wszystkich przypadkach, w których działa. Każde inne rozwiązanie musiałoby być stosowane z najwyższą ostrożnością, ponieważ mogłyby one łatwo wprowadzić błędy w czasie wykonywania.

użytkownik1751825
źródło
Nie działa to w przypadkach, gdy istnieje nieznana liczba parametrów (no cóż ... nie bez użycia roslyn lub codedom do wstępnej kompilacji instrukcji w celu dopasowania liczby parametrów w danym momencie wykonania).
StingyJack
@StingyJack To nie jest przeznaczone. Robi dokładnie to, co? operator robi.
user1751825
2

Sprawdź dokumentację Microsoft dotyczącą If Operator (Visual Basic) tutaj: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/if-operator

If( [argument1,] argument2, argument3 )

Oto kilka przykładów (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
źródło
1
Miły! Usuwam komentarz!
Alec