?. И? () операторы с пустым значением (Visual Basic)
Проверяет значение левого операнда для null (Nothing
) перед выполнением операции доступа к члену (?.
) или индекса (?()
), возвращает значение Nothing
, если левый операнд оценивается Nothing
. Обратите внимание, что в выражениях, которые обычно возвращают типы значений, оператор null-условно возвращает значение Nullable<T>.
Эти операторы помогают создавать меньше кода для обработки значений NULL проверка, особенно при убыванию в структуры данных. Например:
' Nothing if customers is Nothing
Dim length As Integer? = customers?.Length
' Nothing if customers is Nothing
Dim first As Customer = customers?(0)
' Nothing if customers, the first customer, or Orders is Nothing
Dim count As Integer? = customers?(0)?.Orders?.Count()
Для сравнения альтернативный код для первого из этих выражений без условного оператора NULL:
Dim length As Integer?
If customers IsNot Nothing Then
length = customers.Length
Else
length = Nothing
End If
Иногда необходимо выполнить действие для объекта, который может иметь значение NULL, в зависимости от значения логического элемента для этого объекта (например, логическое свойство IsAllowedFreeShipping
в следующем примере):
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
ApplyFreeShippingToOrders(customer)
End If
Вы можете сократить код и избежать ручного проверка для null с помощью оператора с условным значением NULL следующим образом:
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)
Операторы с условием NULL предусматривают сокращенную обработку. Если одна операция в цепочке условного доступа к члену и операции индексов возвращается Nothing
, остальная часть выполнения цепочки останавливается. В следующем примере C(E)
не вычисляется, если A
B
, или C
вычисляется значение Nothing
.
A?.B?.C?(E)
Обратите внимание, что если Not someStr?.Contains("some string")
или какое-либо другое значение, которое оценивается как Boolean?
значение nothing
или HasValue=false
else
, блок выполняется. Оценка следует оценке SQL, где значение NULL/nothing не равно ничего, а не даже другое значение NULL/nothing.
Другим способом, используемым для доступа к члену с значением NULL, является вызов делегатов в потокобезопасном режиме с гораздо меньшим количеством кода. В следующем примере определяются два типа, a NewsBroadcaster
и a NewsReceiver
. Новости отправляются получателю делегатом NewsBroadcaster.SendNews
.
Public Module NewsBroadcaster
Dim SendNews As Action(Of String)
Public Sub Main()
Dim rec As New NewsReceiver()
Dim rec2 As New NewsReceiver()
SendNews?.Invoke("Just in: A newsworthy item...")
End Sub
Public Sub Register(client As Action(Of String))
SendNews = SendNews.Combine({SendNews, client})
End Sub
End Module
Public Class NewsReceiver
Public Sub New()
NewsBroadcaster.Register(AddressOf Me.DisplayNews)
End Sub
Public Sub DisplayNews(newsItem As String)
Console.WriteLine(newsItem)
End Sub
End Class
Если в списке SendNews
вызовов нет элементов, SendNews
делегат создает исключение NullReferenceException. Перед условными операторами NULL код, как показано ниже, убедитесь, что список вызовов делегата не Nothing
был:
SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
SendNews("Just in...")
End If
Новый способ гораздо проще:
SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")
Новый способ является потокобезопасным, так как компилятор создает код для вычисления SendNews
только один раз, запоминая результат во временной переменной. Необходимо явно вызывать метод Invoke
, так как отсутствует синтаксис SendNews?(String)
для вызова делегатов с условием NULL.