?. und? () nullbedingte Operatoren (Visual Basic)

Diese Operatoren testen, ob der Wert des linken Operanden null (Nothing) ist, bevor ein Memberzugriffs- (?.) oder Indexzugriffsvorgang (?()) ausgeführt wird. Sie geben Nothing zurück, wenn der linke Operand Nothing ergibt. Beachten Sie, dass in Ausdrücken, die Werttypen ordinär zurückgeben, der Null-bedingte Operator einen Nullable<T>.

Mithilfe dieser Operatoren müssen Sie für die Prüfung auf null weniger Code schreiben, insbesondere beim tieferen Eindringen in Datenstrukturen. Zum Beispiel:

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

Im Vergleich dazu lautet der alternative Code für den ersten dieser Ausdrücke ohne nullbedingter Operator:

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

Manchmal müssen Sie eine Aktion für ein Objekt ausführen, das null sein kann, basierend auf dem Wert eines booleschen Elements für dieses Objekt (wie die boolesche Eigenschaft IsAllowedFreeShipping im folgenden Beispiel):

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

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

Sie können den Code kürzen und die manuelle Überprüfung auf NULL vermeiden, indem Sie den Operator null-bedingt wie folgt verwenden:

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

If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)

Die NULL-bedingten Operatoren sind Kurzschlussoperatoren. Wenn ein Vorgang in einer Kette von bedingten Memberzugriffs- und Indexvorgängen Nothing zurückgibt, wird die restliche Ausführung der Kette angehalten. Im folgenden Beispiel wird C(E) nicht ausgewertet, wenn A, B oder C als Nothing ausgewertet wird.

A?.B?.C?(E)

Beachten Sie, dass der else-Block ausgeführt, wenn Not someStr?.Contains("some string") oder ein anderer Wert, der als Boolean? ausgewertet wird, den Wert „nothing“ oder „HasValue=false“ aufweist. Die Auswertung folgt der SQL-Auswertung, bei der null/nichts nichts bedeutet, nicht einmal ein weiteres null/nichts.

Ein weiterer Verwendungszweck für den null-bedingten Memberzugriff ist das Aufrufen von Delegaten auf threadsichere Weise mit viel weniger Code. Im folgenden Beispiel werden zwei Typen definiert: ein NewsBroadcaster und ein NewsReceiver. Nachrichtenelemente werden vom NewsBroadcaster.SendNews Delegaten an den Empfänger gesendet.

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

Wenn in der SendNews Aufrufliste keine Elemente vorhanden sind, löst der SendNews Delegat eine NullReferenceException aus. Vor null-bedingten Operatoren sorgten Code wie die folgenden dafür, dass die Aufrufliste der Stellvertretung nicht Nothinglautete:

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

Die neue Methode ist viel einfacher:

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

Die neue Methode ist threadsicher, da der Compiler Code zum Auswerten von SendNews nur einmal generiert und das Ergebnis in einer temporären Variablen behält. Sie müssen die Invoke-Methode explizit aufrufen, da es keine Aufrufsyntax für Null-Bedingungsdelegate gibt SendNews?(String).

Siehe auch