?. 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 Nothing
lautete:
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)
.