?. I? () operatory warunkowe o wartości null (Visual Basic)

Testuje wartość operandu po lewej stronie dla wartości null (Nothing) przed wykonaniem operacji dostępu do składowej (?.) lub indeksu (?()) ; zwraca Nothing wartość , jeśli operand po lewej stronie zwróci wartość Nothing. Należy pamiętać, że w wyrażeniach, które zwykle zwracają typy wartości, operator warunkowy o wartości null zwraca wartość Nullable<T>.

Te operatory ułatwiają pisanie mniejszej ilości kodu w celu obsługi kontroli wartości null, zwłaszcza w przypadku malenia w strukturach danych. Na przykład:

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

Dla porównania alternatywnym kodem dla pierwszego z tych wyrażeń bez operatora warunkowego o wartości null jest:

Dim length As Integer?
If customers IsNot Nothing Then
   length = customers.Length
Else
    length = Nothing
End If

Czasami należy wykonać akcję dla obiektu, który może mieć wartość null, na podstawie wartości elementu członkowskiego logicznego dla tego obiektu (na przykład właściwości IsAllowedFreeShipping logicznej w poniższym przykładzie):

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
  ApplyFreeShippingToOrders(customer)
End If

Możesz skrócić kod i uniknąć ręcznego sprawdzania wartości null przy użyciu operatora warunkowego o wartości null w następujący sposób:

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)

Operatory warunkowe o wartości null są zwarciem. Jeśli jedna operacja w łańcuchu dostępu warunkowego i operacji indeksowania elementu członkowskiego zwróci wartość Nothing, pozostałe operacje wykonywania łańcucha zostaną zatrzymane. W poniższym przykładzie nie jest obliczana, C(E) jeśli Awartość , Blub C zwraca wartość Nothing.

A?.B?.C?(E)

Należy pamiętać, że jeśli Not someStr?.Contains("some string") lub jakakolwiek inna wartość, która ocenia jako Boolean? wartość nothing lub HasValue=false, else blok jest uruchamiany. Ocena jest zgodna z oceną SQL, w której wartość null/nic nie jest równa niczego, a nawet innej wartości null/nic.

Innym zastosowaniem dostępu warunkowego o wartości null jest wywoływanie delegatów w bezpieczny wątkowo sposób z znacznie mniejszym kodem. W poniższym przykładzie zdefiniowano dwa typy: a NewsBroadcaster i NewsReceiver. Elementy wiadomości są wysyłane do odbiorcy przez delegata 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

Jeśli na liście wywołań nie ma żadnych elementów SendNews , SendNews delegat zgłasza element NullReferenceException. Przed operatorami warunkowymi o wartości null kod podobny do poniższego upewnił się, że lista wywołań delegata nie Nothingbyła następująca:

SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
   SendNews("Just in...")
End If

Nowy sposób jest znacznie prostszy:

SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")

Nowy sposób jest bezpieczny wątkowo, ponieważ kompilator generuje kod do oceny SendNews tylko raz, zachowując wynik w zmiennej tymczasowej. Należy jawnie wywołać metodę Invoke , ponieważ nie ma składni SendNews?(String)wywołania delegata o wartości null.

Zobacz też