web-dev-qa-db-fra.com

C # Opérateur de propagation nul / Expression d'accès conditionnel et blocs if

Opérateur de propagation nul/Expression d'accès conditionnel entrant c # -6. ressemble à une fonctionnalité très pratique. Mais je suis curieux de savoir si cela aidera à résoudre le problème de vérifier si un membre enfant n'est pas nul, puis d'appeler une méthode booléenne sur ledit membre enfant à l'intérieur d'un bloc if:

  public class Container<int>{
       IEnumerable<int> Objects {get;set;}
  }

  public Container BuildContainer()
  { 
      var c = new Container();

      if (/* Some Random Condition */)
         c.Objects = new List<int>{1,2,4};
  }

  public void Test()
  {
      var c = BuildContainer();

      //Old way
      if ( null != c && null != c.Objects && c.Objects.Any())
         Console.Write("Container has items!");


      //C# 6 way?
      if (c?.Object?.Any())
          Console.Write("Container has items!");
  }

Est-ce que c?.Object?.Any() compilera? Si l'opérateur de propagation court-circuite (je suppose que c'est le bon terme) à null, vous avez if (null), qui n'est pas valide.

L'équipe C # répondra-t-elle à cette préoccupation ou manque-t-il le cas d'utilisation prévu pour l'opérateur de propagation nul?

21
Philip Pittle

Cela ne fonctionnera pas de cette façon. Vous pouvez simplement sauter l'explication et voir le code ci-dessous :)

Comme vous le savez, l'opérateur ?. Retournera null si un membre enfant est null. Mais que se passe-t-il si nous essayons d'obtenir un membre non nullable, comme la méthode Any(), qui renvoie bool? La réponse est que le compilateur "encapsulera" une valeur de retour dans Nullable<>. Par exemple, Object?.Any() nous donnera bool? (Qui est Nullable<bool>), Pas bool.

La seule chose qui ne nous permet pas d'utiliser cette expression dans l'instruction if est qu'elle ne peut pas être implicitement castée en bool. Mais vous pouvez faire la comparaison explicitement, je préfère comparer à true comme ceci:

if (c?.Object?.Any() == true)
    Console.Write("Container has items!");

Merci à @DaveSexton il y a une autre façon:

if (c?.Object?.Any() ?? false)
    Console.Write("Container has items!");

Mais pour moi, la comparaison avec true semble plus naturelle :)

44
Eldar Dordzhiev

L'opérateur null-conditionnel retournerait null ou la valeur à la fin de l'expression. Pour types de valeur Il renverra le résultat dans Nullable<T>, donc dans votre cas, ce serait Nullabe<bool>. Si nous regardons l'exemple dans le document pour Fonctionnalités à venir en C # (spécifié ici ) , il a un exemple:

int? first = customers?[0].Orders.Count();

Dans l'exemple ci-dessus, au lieu de int, Nullable<int> serait retourné. Pour bool, il renverra Nullable<bool>.

Si vous essayez le code suivant dans CTP Visual Studio "14" :

Nullable<bool> ifExist = c?.Objects?.Any();

Le résultat de la ligne ci-dessus serait un Nullable<bool>/bool?. Plus tard, vous pouvez faire la comparaison comme:

Utilisation de opérateur de coalescence nulle ??

 if (c?.Object?.Any() ?? false)

En utilisant Nullable<T>.GetValueOrDefault Méthode

if ((c?.Objects?.Any()).GetValueOrDefault())

Utilisation de la comparaison avec true

if (c?.Objects?.Any() == true)
6
Habib