?. Operadores condicionales NULL ?. y ?() (Visual Basic)
Comprueba el valor del operando izquierdo para NULL (Nothing
) antes de realizar una operación de acceso a miembro (?.
) o índice (?()
); devuelve Nothing
si el operando izquierdo se evalúa como Nothing
. Tenga en cuenta que, en expresiones que suelen devolver tipos de valor, el operador condicional NULL devuelve un Nullable<T>.
Estos operadores ayudan a escribir menos código para controlar las comprobaciones de valores NULL, especialmente para descender a estructuras de datos. Por ejemplo:
' 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()
Para la comparación, el código alternativo para la primera de estas expresiones sin un operador condicional NULL es:
Dim length As Integer?
If customers IsNot Nothing Then
length = customers.Length
Else
length = Nothing
End If
A veces, debe realizar una acción en un objeto que puede ser NULL, en función del valor de un miembro booleano en ese objeto (como la propiedad booleana IsAllowedFreeShipping
en el ejemplo siguiente):
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
ApplyFreeShippingToOrders(customer)
End If
Puede acortar el código y evitar la comprobación manual de valores NULL mediante el operador condicional NULL de la manera siguiente:
Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.
If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)
Los operadores de condición NULL se cortocircuitan. Si una operación en una cadena de la operación de índice y de acceso a miembros condicional devuelve Nothing
, se detiene el resto de la ejecución de la cadena. En el ejemplo siguiente, C(E)
no se evalúa si A
, B
o C
se evalúa como Nothing
.
A?.B?.C?(E)
Tenga en cuenta que si Not someStr?.Contains("some string")
o cualquier otro valor que se evalúe como Boolean?
tiene el valor de nothing
o HasValue=false
, el bloque else
se ejecutará. La evaluación sigue la evaluación de SQL donde null/nothing no es igual a nada, ni siquiera a otro null/nothing.
Otro uso para el acceso a miembros de condición NULL es invocar delegados de manera segura para los subprocesos con mucho menos código. En el ejemplo siguiente, se definen dos tipos, NewsBroadcaster
y NewsReceiver
. El delegado NewsBroadcaster.SendNews
envía elementos nuevos al receptor.
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
Si no hay ningún elemento en la lista de invocación SendNews
, el delegado SendNews
genera una excepción NullReferenceException. Antes de los operadores condicionales NULL, código como el siguiente garantizaba que la lista de invocación de delegados no era Nothing
:
SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
SendNews("Just in...")
End If
La nueva manera es mucho más sencilla:
SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")
La nueva forma de hacerlo es segura para los subprocesos porque el compilador genera código para evaluar SendNews
solo una vez, manteniendo el resultado en una variable temporal. Debe llamar explícitamente al método Invoke
porque no hay ninguna sintaxis de invocación del delegado null condicional SendNews?(String)
.