40 votes

Extension de LINQ pour accepter les énumérables nullables

Tout en travaillant avec des extensions Linq, il est normal de voir le code comme ceci:

IEnumerable<int> enumerable = GetEnumerable();
int sum = 0;
if (enumerable != null)
{
    sum = enumerable.Sum();
}

Afin d'améliorer la qualité du code, j'ai écrit la suite de l'extension de la méthode qui vérifie nullable enumerables et rompt le linq exécution.

public static IEnumerable<T> IgnoreIfEmpty<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null) yield break;
    foreach (var item in enumerable)
    {
        yield return item;
    }
}

Donc, je peux refactoriser le code comme ceci:

var sum = GetEnumerable().IgnoreIfEmpty().Sum();

Mes questions maintenant:

  1. Quelles sont les sanctions associées avec mon extension de la méthode au moment de l'exécution?
  2. Est-ce une bonne pratique pour étendre linq de cette façon?

Mise à jour: Mon framework cible est: 3.5

40voto

Yuval Itzchakov Points 13820

Quelles sont les sanctions associées avec mon extension de la méthode au moment de l'exécution?

Votre méthode d'extension est transformé en une machine d'état, il y a ainsi un minimum de frais généraux, mais qui ne devrait pas être perceptible.

Est-ce une bonne pratique pour étendre linq de cette façon?

Dans votre question, vous dites:

Tout en travaillant avec des extensions Linq, il est normal de voir ce type de code (insérer énumérable null vérifier ici)

Et je prie de différer. La pratique courante dit de ne pas retourner la valeur null lorsque l' IEnumerable<T> est attendue. La plupart des cas, doit retourner un vide collection (ou IEnumerable), laissant null à la exceptionnel, parce que null n'est pas vide. Ce serait faire de votre méthode entièrement redondantes. Utiliser Enumerable.Empty<T> en cas de besoin.

29voto

Bas Brekelmans Points 13799
  1. Vous allez avoir un appel de la méthode des frais généraux, il sera négligeable, sauf si vous exécutez dans une boucle ou une performance criticial scénario. Ce n'est qu'une ombre en comparaison à quelque chose comme une base de données d'appeler ou d'écrire à un système de fichiers. Notez que la méthode ne va probablement pas à être incorporé, puisque c'est un agent recenseur.
  2. Il est tout au sujet de la lisibilité / maintenabilité. Que dois-je attendre quand je la vois, GetEnumerable().IgnoreIfEmpty().Sum();? Dans ce cas, c'est logique.

Notez qu'avec C# 6, nous pouvons utiliser la syntaxe suivante: GetEnumerable()?.Sum() qui retourne un int?. Vous pouvez écrire GetEnumerable()?.Sum() ?? 0 ou GetEnumerable()?.Sum().GetValueOrDefault() pour obtenir une valeur non nulle entier qui sera par défaut à zéro.

Si vous êtes vraiment soucieux de performances, vous pouvez aussi légèrement de refactoriser votre méthode de sorte qu'il n'est pas un agent recenseur. Cela peut augmenter les chances de l'in-lining, bien que je n'ai aucune idée de l '"arcane" logique de le compilateur JIT:

public static IEnumerable<T> IgnoreIfEmpty<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null) return Enumerable.Empty<T>();
    return enumerable;
}

Plus généralement, sur l'extension Linq, je pense qu'il est parfaitement acceptable, pourvu que le code du sens. MSDN a même un article à ce sujet. Si vous regardez la norme Where, Select méthodes de Linq, et d'oublier les optimisations de performances qu'ils ont là, toutes les techniques sont principalement des one-liner méthodes.

14voto

w.b Points 2408

Vous pouvez ignorer la méthode d'extension supplémentaire et utiliser un opérateur de coalescence nulles: voici son objectif. Une vérification ponctuelle de la nullité devrait être beaucoup plus efficace qu'une autre machine à états:

 IEnumerable<int> enumerable = GetEnumerable();
int sum = 0;

sum = (enumerable ?? Enumerable.Empty<int>()).Sum();
 

-1voto

akshaymishra14 Points 86

La plupart du temps, nous écrivons beaucoup de code simplement parce que nous sommes enchantés par la beauté de notre création - non pas parce que nous en avons vraiment besoin - et que nous appelons cela abstraction, réutilisabilité, extensibilité, etc.

Cette pièce brute est-elle moins lisible ou moins extensible ou moins réutilisable ou plus lente:

 var sum = GetEnumerable().Where(a => a != null).Sum(); 
 

Moins vous écrivez de code - moins vous testez de code - restez simple. BTW - il est bon d'écrire des méthodes d'extension si vous pouvez le justifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X