web-dev-qa-db-fra.com

Resharper: énumération multiple possible de IEnumerable

J'utilise la nouvelle version de Resharper 6. À plusieurs endroits de mon code, il a souligné du texte et m'a averti qu'il pouvait y avoir Énumération multiple possible de IEnumerable.

Je comprends ce que cela signifie et j'ai suivi les conseils le cas échéant, mais dans certains cas, je ne suis pas sûr que ce soit vraiment un gros problème.

Comme dans le code suivant:

var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties();
if (properties.Contains("Property1") || properties.Contains("Property2") || properties.Contains("Property3")) {
    ...
}

Il souligne chaque mention de properties sur la deuxième ligne, avertissant que j'énumère plusieurs fois cet IEnumerable.

Si j'ajoute .ToList() à la fin de la ligne 1 (en transformant properties d'un IEnumerable<string> En un List<string>), Les avertissements disparaissent.

Mais sûrement, si je le convertis en une liste, il énumérera tout le IEnumerable pour créer la liste en premier lieu, puis énumérera la liste comme requis pour trouver les propriétés (c'est-à-dire 1 énumération complète et 3 énumérations partielles ). Alors que dans mon code d'origine, il ne fait que les 3 énumérations partielles.

Ai-je tort? Quelle est la meilleure méthode ici?

37
Ross

Je ne sais pas exactement ce que votre properties est vraiment ici - mais s'il représente essentiellement une requête de base de données non matérialisée, alors votre instruction if effectuera trois requêtes.

I suspect il vaudrait mieux faire:

string[] propertiesToFind = { "Property1", "Property2", "Property3" };
if (properties.Any(x => propertiesToFind.Contains(x))
{
     ...
}

Cela logiquement ne répétera la séquence qu'une seule fois - et s'il y a une requête de base de données impliquée, il pourrait bien être en mesure d'utiliser simplement une clause SQL "IN" pour tout faire dans la base de données en une seule requête .

41
Jon Skeet

Si vous appelez Contains() sur un IEnumerable, il invoquera la méthode d'extension qui parcourra simplement les éléments afin de le trouver. IList a une implémentation réelle pour Contains() qui est probablement plus efficace qu'une itération régulière à travers les valeurs (il pourrait y avoir un arbre de recherche avec des hachages?), donc il ne prévient pas avec IList.

Étant donné que la méthode d'extension ne sera consciente que c'est un IEnumerable, elle ne peut probablement pas utiliser de méthodes intégrées pour Contains() même s'il serait théoriquement possible d'identifier les types connus et les transtypages en conséquence afin de les utiliser.

6
jishi