?. 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).

Consulte también