在执行成员访问(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)
如果计算结果为,B
则C
不计算A
结果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
该方法,因为没有 null 条件委托调用语法 SendNews?(String)
。