Partage via


?. et les opérateurs conditionnels Null ?() (Visual Basic)

Teste si l’opérande de gauche a une valeur Null (Nothing) avant d’effectuer une opération d’accès au membre (?.) ou d’index (?()) ; retourne Nothing si l’opérande de gauche s’évalue à Nothing. Notez que dans les expressions qui retournent normalement des types valeur, l’opérateur conditionnel Null retourne un Nullable<T>.

Ces opérateurs permettent d’écrire moins de code pour gérer les vérifications Null, notamment lorsqu’on explore des structures de données. Par exemple :

' 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()

À titre de comparaison, le code alternatif pour la première de ces expressions sans opérateur conditionnel Null est :

Dim length As Integer?
If customers IsNot Nothing Then
   length = customers.Length
Else
    length = Nothing
End If

Parfois, vous devez effectuer une action sur un objet qui peut être Null, en fonction de la valeur d’un membre booléen sur cet objet (comme la propriété booléenne IsAllowedFreeShipping dans l’exemple suivant) :

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
  ApplyFreeShippingToOrders(customer)
End If

Vous pouvez raccourcir votre code et éviter de vérifier manuellement la valeur Null à l’aide de l’opérateur conditionnel Null comme suit :

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)

Les opérateurs conditionnels Null ont un effet de court-circuit. Si une opération dans une chaîne d’opérations d’accès au membre et d’indexation conditionnelles retourne Nothing, l’exécution du reste de la chaîne s’arrête. Dans l’exemple suivant, C(E) n’est pas évalué si A, B ou C renvoie la valeur Nothing.

A?.B?.C?(E)

Remarquez que, si Not someStr?.Contains("some string") ou toute autre valeur évaluée comme Boolean?, ayant la valeur nothing ou HasValue=false entraîne l’exécution du bloc else. L’évaluation suit l’évaluation SQL où null/nothing n’est pas égal à n’importe quelle valeur (anything), pas même une autre valeur null/nothing.

L’accès au membre conditionnel Null s’utilise également pour appeler des délégués de façon thread-safe, avec beaucoup moins de code. L’exemple suivant définit deux types, un NewsBroadcaster et un NewsReceiver. Les actualités sont envoyées au destinataire par le délégué 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

S’il n’y a aucun élément dans la liste d’appels SendNews, le délégué SendNews lève une NullReferenceException. Avant les opérateurs conditionnels Null, un code comme le suivant s’assurait que la liste d’appels de délégués n’était pas Nothing :

SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
   SendNews("Just in...")
End If

La nouvelle méthode est beaucoup plus simple :

SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")

La nouvelle méthode est thread-safe, car le compilateur génère du code qui évalue SendNews une seule fois, en conservant le résultat dans une variable temporaire. Vous devez explicitement appeler la méthode Invoke, car il n'existe pas de syntaxe d'appel de délégué conditionnel Null SendNews?(String).

Voir aussi