2017-04-11 1 views
7

J'ai simplifié un morceau d'un code d'exécution différé, mais comment diable vérifiez-vous que ce qui suit n'est pas nul/vide sans l'avoir enveloppé dans un try/catch?Test de 'Izy loaded' null IEnumerable dans C#?

string[] nullCollection = null; 
    IEnumerable<string> ienumerable = new[] { nullCollection }.SelectMany(a => a); 

    bool isnull = ienumerable == null; //returns false 
    bool isany = ienumerable.Any(); //throws an exception 
+0

@MrinalKamboj Il s'agit d'une exception NullReferenceException car le SelectManyIterator est appelé avec un élément nul. –

+0

@RB. alors c'est difficile, aucun des points ci-dessus ne tiendra –

Répondre

3

Vous avez juste besoin de rendre votre lambda plus résistante aux entrées nulles:

IEnumerable<string> ienumerable = new[] { nullCollection } 
    .SelectMany(a => a ?? Enumerable.Empty<string>()); 

bool isany = ienumerable.Any(); // Sets isany to 'false' 
+0

C'est sympa, mais si je viens de passer un argument 'IEnumerable ' je suppose que je suis coincé ... – maxp

+0

@maxp Yep - il y a un problème fondamental avec la construction de 'ienumerable'. Je ne pense pas qu'il y ait de solution. –

2

Vous pouvez vérifier si l'élément en cours de la recenseur est nulle

string[] nullCollection = null; 
IEnumerable<string> ienumerable = new[] { nullCollection }.SelectMany(a => a); 

bool isnull = ienumerable.GetEnumerator().Current == null; 
if (!isnull) 
{ 
    bool isany = ienumerable.Any(); 
} 
+1

Cela ne fonctionnera pas - quand vous appelez 'MoveNext()' pour itérer, il se bloquera s'il rencontre un élément 'null'. En fin de compte, la fonction de projection va être évaluée pour chaque élément, et cela causera un plantage quand elle est appelée avec une valeur nulle - je ne pense pas qu'il y en ait. –

+2

@RB. W/o 'MoveNext()', il n'y a pas 'Current' :). Est-il de retour à la case un? –

+3

Ceci est une réponse tout à fait incorrecte - l'accès 'Current' avant que' MoveNext' ait un comportement indéfini - probablement ici, il renvoie toujours 'null'. –

3

Vous ne pouvez pas faire , parce que c'est la même chose que de demander "comment puis-je dire que cette méthode ne lancera pas NullReferenceException sans l'invoquer?". N'ayant pas d'autres indices, le seul moyen est d'invoquer de telles méthodes et d'observer le résultat. Énumérer IEnumerable appelle simplement un tas d'appels MoveNext sur son énumérateur, et un tel appel pourrait jeter des exceptions.

0

Puisque les méthodes Linq sont des méthodes d'extension sur IEnumerable, vous pouvez envelopper ces extensions plus loin: avec une méthode d'extension, l'objet recevant l'extension peut être nul.

public static IEnumerable<TResult> SafeSelectMany<T, TCollection, TResult>(
      this IEnumerable<T> source, 
      Func<T, IEnumerable<TCollection>> collectionSelector, 
      Func<T, TCollection, TResult> resultSelector) 
    { 
     if (source == null) 
     { 
      return null; 
     } 
     IEnumerable<TResult> result = source.SelectMany(collectionSelector, resultSelector); 
     return result; 
    } 

Vous pouvez également retourner un List<TResult> vide au lieu de null pour source==null.