?. Och? () null-villkorsstyrda operatorer (Visual Basic)
Testar värdet för den vänstra operanden för null (Nothing
) innan en medlemsåtkomståtgärd (?.
) eller index (?()
) utförs. Returnerar Nothing
om den vänstra operanden utvärderas till Nothing
. Observera att i uttryck som normalt returnerar värdetyper returnerar den null-villkorsstyrda operatorn en Nullable<T>.
De här operatorerna hjälper dig att skriva mindre kod för att hantera null-kontroller, särskilt när du går ned i datastrukturer. Till exempel:
' 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()
Som jämförelse är den alternativa koden för det första av dessa uttryck utan en null-villkorsoperator:
Dim length As Integer?
If customers IsNot Nothing Then
length = customers.Length
Else
length = Nothing
End If
Ibland måste du vidta en åtgärd för ett objekt som kan vara null, baserat på värdet för en boolesk medlem i objektet (som den booleska egenskapen IsAllowedFreeShipping
i följande exempel):
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
ApplyFreeShippingToOrders(customer)
End If
Du kan förkorta koden och undvika att manuellt söka efter null med hjälp av den null-villkorsstyrda operatorn på följande sätt:
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)
De null-villkorsstyrda operatorerna kortsluter. Om en åtgärd i en kedja av villkorlig medlemsåtkomst och indexåtgärder returnerar Nothing
stoppas resten av kedjans körning. I följande exempel C(E)
utvärderas inte om A
, B
eller C
utvärderas till Nothing
.
A?.B?.C?(E)
Observera att om Not someStr?.Contains("some string")
eller något annat värde som utvärderas som Boolean?
har värdet nothing
för eller HasValue=false
, else
körs blocket. Utvärderingen följer SQL-utvärderingen där null/ingenting inte är lika med något, inte ens en annan null/ingenting.
En annan användning för null-villkorlig medlemsåtkomst är att anropa ombud på ett trådsäkert sätt med mycket mindre kod. I följande exempel definieras två typer, en NewsBroadcaster
och en NewsReceiver
. Nyhetsobjekt skickas till mottagaren av ombudet 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
Om det inte finns några element i SendNews
anropslistan genererar ombudet SendNews
en NullReferenceException. Innan null-villkorsoperatorer såg kod som följande till att listan över delegerade anrop inte Nothing
var :
SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
SendNews("Just in...")
End If
Det nya sättet är mycket enklare:
SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")
Det nya sättet är trådsäkert eftersom kompilatorn genererar kod för att endast utvärdera SendNews
en gång, vilket behåller resultatet i en tillfällig variabel. Du måste uttryckligen Invoke
anropa metoden eftersom det inte finns någon null-villkorlig delegatanropssyntax SendNews?(String)
.