web-dev-qa-db-fra.com

Est-ce que si (items! = Null) est superflu avant foreach (T item dans items)?

Je rencontre souvent un code comme celui-ci:

if ( items != null)
{
   foreach(T item in items)
   {
        //...
   }
}

Fondamentalement, la condition if garantit que le bloc foreach ne sera exécuté que si items n'est pas null. Je me demande si la condition if est vraiment nécessaire ou si foreach gérera le cas si items == null

Je veux dire, je peux simplement écrire 

foreach(T item in items)
{
    //...
}

sans se soucier de savoir si items est null ou non? La condition if est-elle superflue? Ou cela dépend du type de items ou peut-être de T également?

66
Nawaz

Vous devez toujours vérifier si (items! = Null) sinon vous obtiendrez NullReferenceException. Cependant, vous pouvez faire quelque chose comme ça:

List<string> items = null;  
foreach (var item in items ?? new List<string>())
{
    item.Dump();
}

mais vous pouvez en vérifier les performances. Je préfère donc toujours avoir si (items! = Null) en premier.

Sur la suggestion d'Eric Lippert, j'ai changé le code en:

List<string> items = null;  
foreach (var item in items ?? Enumerable.Empty<string>())
{
    item.Dump();
}
79
Vlad Bezden

En utilisant C # 6, vous pouvez utiliser le nouvel opérateur conditionnel null avec List<T>.ForEach(Action<T>) (ou votre propre méthode IEnumerable<T>.ForEach extension).

List<string> items = null;
items?.ForEach(item =>
{
    // ...
});
42
kjbartel

La vraie chose à retenir ici devrait être une séquence ne devrait presque jamais être nulle en premier lieu . Faites-en simplement un invariant dans tous vos programmes que si vous avez une séquence, elle n’est jamais nulle. Il est toujours initialisé pour être la séquence vide ou une autre séquence authentique. 

Si une séquence n'est jamais nulle, alors vous n'avez évidemment pas besoin de la vérifier. 

32
Eric Lippert

En réalité, il existe une demande de fonctionnalité sur ce @Connect: http://connect.Microsoft.com/VisualStudio/feedback/details/93497/foreach-should-chould-for-null

Et la réponse est assez logique: 

Je pense que la plupart des boucles foreach sont écrit dans l’intention d’itérer un collection non nulle. Si tu essayes itérant via null, vous devriez obtenir votre exception, de sorte que vous pouvez réparer votre code.

9
Teoman Soygul

Vous pouvez toujours le tester avec une liste nulle ... mais c'est ce que j'ai trouvé sur le site Web msdn

foreach-statement:
    foreach   (   type   identifier   in   expression   )   embedded-statement 

Si expression a la valeur null, une exception System.NullReferenceException est levée.

5
nbz

Vous pouvez encapsuler le contrôle nul dans une méthode d'extension et utiliser un lambda:

public static class EnumerableExtensions {
  public static void ForEach<T>(this IEnumerable<T> self, Action<T> action) {
    if (self != null) {
      foreach (var element in self) {
        action(element);
      }
    }
  }
}

Le code devient:

items.ForEach(item => { 
  ...
});

If peut être encore plus concis si vous souhaitez simplement appeler une méthode qui prend un élément et renvoie void:

items.ForEach(MethodThatTakesAnItem);
2
Jordão

Ce n'est pas superflous. Au moment de l'exécution, les éléments seront convertis en un IEnumerable et sa méthode GetEnumerator sera appelée. Cela entraînera un déréférencement des éléments qui échoueront

1
boca

Vous avez besoin de ça. Vous obtiendrez une exception lorsque foreach accédera au conteneur pour configurer l'itération autrement.

Sous les couvertures, foreach utilise une interface implémentée dans la classe de collection pour effectuer l'itération. L’interface générique équivalente est ici .

La déclaration foreach du C # langage (pour chacun dans Visual Basic) cache la complexité de la les recenseurs. Par conséquent, en utilisant foreach est recommandé au lieu de directement manipuler l'énumérateur.

0
Steve Townsend

En C # 6, vous pouvez écrire ça comme ceci:

// some string from file or UI, i.e.:
// a) string s = "Hello, World!";
// b) string s = "";
// ...
var items = s?.Split(new char[] { ',', '!', ' ' }) ?? Enumerable.Empty<string>();  
foreach (var item in items)
{
    //..
}

C'est fondamentalement la solution de Vlad Bezden mais en utilisant le ?? expression pour toujours générer un tableau qui n'est pas nul et qui survit donc au foreach plutôt que d'avoir cette vérification à l'intérieur du crochet foreach.

0
dr. rai

Le test est nécessaire, car si la collection est null, foreach lève une exception NullReferenceException. C'est en fait assez simple d'essayer.

List<string> items = null;
foreach(var item in items)
{
   Console.WriteLine(item);
}
0
Marius Bancila

le second lancera une NullReferenceException avec le message Object reference not set to an instance of an object.

0
harryovers

Comme mentionné ici vous devez vérifier si cela n’est pas nul.

N'utilisez pas une expression dont la valeur est null.

0
Reniuz