Есть ли VB.NET-эквивалент для C # 's' ?? ' оператор?

180

Есть ли VB.NET-эквивалент для ??оператора C # ?

Натан Куп
источник
4
Большинство ответов здесь (включая принятый ответ) не являются правильными и не являются функционально эквивалентными во всех ситуациях. Правильный эквивалент - оператор if () с 2 аргументами. Однако второй аргумент может быть вложенным для достижения точно таких же результатов, как с несколькими аргументами.
user1751825
Вы имеете в виду троичный оператор?: Например, return ((значение <0)? True: false)
Zeek2

Ответы:

155

Используйте If()оператор с двумя аргументами ( документация 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
источник
3
Я думаю, что If()утверждение в VB такое же, как if...?...:в C #, а не ??оператор
Люк Т О'Брайен
2
@ LukeTO'Brien Вот если вы используете это с 3 аргументами. Если вы используете его с 2 аргументами, это больше ??(см. Другой ответ на этот вопрос: stackoverflow.com/a/20686360/1474939 )
Брайан Дж
2
Этот ответ показывает, как использовать VB If с тремя параметрами . Это не похоже на ??оператор C # . Лучшим ответом будет код Maverick's If с двумя аргументами . (Ник имел аналогичный ответ, несколько лет назад, но не включает объяснения из MSDN.)
ToolmakerSteve
1
Это отвечает на совершенно другой вопрос.
Марк Гравелл
1
Чтобы понять предыдущие комментарии, посмотрите историю изменений.
Зев Шпиц
70

Принятый ответ не имеет никакого объяснения и является просто ссылкой.
Поэтому я решил оставить ответ, объясняющий, как Ifработает оператор, взятый из MSDN:


Если оператор (Visual Basic)

Использует оценку короткого замыкания для условного возврата одного из двух значений. Оператор If может быть вызван с тремя аргументами или с двумя аргументами.

If( [argument1,] argument2, argument3 )


Если оператор вызван с двумя аргументами

Первый аргумент для If может быть опущен. Это позволяет вызывать оператор, используя только два аргумента. Следующий список применяется только тогда, когда оператор If вызывается с двумя аргументами.


части

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.


Когда логический аргумент опущен, первый аргумент должен быть ссылочным или обнуляемым типом. Если первый аргумент имеет значение Nothing , возвращается значение второго аргумента. Во всех остальных случаях возвращается значение первого аргумента. Следующий пример иллюстрирует, как работает эта оценка.


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

Пример того, как обрабатывать более двух значений (вложенных 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)))
Код Маверик
источник
18

Вы можете использовать метод расширения. Этот работает как SQL COALESCEи, вероятно, излишним для того, что вы пытаетесь проверить, но это работает.

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

Встроенный If(nullable, secondChoice)может обрабатывать только два обнуляемых выбора. Здесь можно Coalesceуказать столько параметров, сколько нужно. Будет возвращен первый ненулевой, а остальные параметры не будут оцениваться после этого (короткое замыкание, например AndAlso/ &&и OrElse/ ||)

StingyJack
источник
8
Потому что в языке есть встроенный оператор. Нет причин даже смотреть на методы расширения.
Ник
2
Я не собираюсь повторять чужой ответ. Я подумал, что было бы неплохо предложить альтернативное решение, если вам нужно проверить несколько значений с помощью одного оператора. Так как это не НЕПРАВИЛЬНЫЙ ответ, то должно ли оно быть понижено?
StingyJack
1
+1 за предоставление реализации с использованием обобщений и избежание приведения типов /
упаковки
4
@ Ник, прости, но ты просто неправ. Если у вас есть более двух объединенных аргументов, встроенная функция не обрезает его.
toddmo
Вы можете пропустить параметр obj и позволить телу быть Return args.FirstOrDefault(Function(arg) arg IsNot Nothing):-)
Ульф Акерстедт
11

Одним из существенных ограничений большинства этих решений является то, что они не будут закорачиваться. Поэтому они на самом деле не эквивалентны?? .

Встроенный If оператор не будет оценивать последующие параметры, если более ранний параметр ничего не оценивает.

Следующие утверждения эквивалентны:

C #

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

VB

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

Это будет работать во всех случаях, когда ??работает. Любое другое решение должно использоваться с особой осторожностью, поскольку оно может легко привести к ошибкам во время выполнения.

user1751825
источник
Это не работает в тех случаях, когда существует неизвестное количество параметров (ну ... не без использования roslyn или codedom для предварительной компиляции оператора, чтобы соответствовать количеству параметров в тот момент выполнения).
StingyJack
@StingyJack Это не предназначено для. Это делает именно то, что ?? оператор делает.
user1751825
2

Ознакомьтесь с документацией Microsoft об операторе If (Visual Basic) здесь: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/if-operator

If( [argument1,] argument2, argument3 )

Вот несколько примеров (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
источник
1
Ницца! Удаление комментария!
Алек