2010-02-10 4 views
3

J'ai appris le C# en 2006, et j'ai récemment essayé de revenir en arrière. J'ai appris alors qu'ils ont ajouté quelque chose appelé LINQ Extensions à C# 3.0. Maintenant, je suis familier avec les méthodes d'extension, et je réfléchis juste aux détails de ceux liés à IEnumerables.Comment une extension LINQ enchaîne-t-elle d'autres extensions?

Plus tôt aujourd'hui, moi et un de mes collègues se demandaient si oui ou non les blocs de code suivants sont équivalents:

List<int> integers; 
IEnumerable<int> subResult = items.Where(i => IsPrime(i)); 
IEnumerable<int> orderedResult = subResult.OrderBy(i => i); 

contre

List<int> integers; 
IEnumerable<int> result = items.Where(i => IsPrime(i)).OrderBy(i => i); 

Il m'a dit la dernière était plus efficace car l'extension a utilisé l'interrogation tardive de sa source. Je ne suis pas sûr d'avoir compris ce qu'il voulait dire, et je me demandais s'il avait raison.

Répondre

5

Ils sont équivalents. Ils utilisent tous deux l'évaluation paresseuse/l'interrogation tardive. Cela signifie que lorsque la méthode .Where est appelée, elle n'effectue aucune énumération réelle de la liste, elle garde seulement une référence à son entrée et à la condition qu'elle va vérifier et stocke ces références. Lorsque la méthode GetEnumerator est appelée plus tard le résultat .Where, .Where entre en action.

Même chose avec .OrderBy. Il ne fait pas d'énumération de la liste jusqu'à ce que .GetEnumerator soit appelé.

Ce truc peut être difficile à comprendre mais il y a quelques très bons moyens d'en apprendre plus. Le premier est d'écrire un exemple simple comme vous l'avez, de préférence divisé en plusieurs lignes, avec une simple boucle for-each pour itérer tous les éléments. Déboguez le code et parcourez ligne par ligne. Voyez comment le débogueur saute. Il est très déroutant au début, mais parcouru quelques fois et vous comprendrez comment l'évaluation paresseuse fonctionne. Jon Skeet a également une superbe démo pour visualiser LINQ.

https://msmvps.com/blogs/jon_skeet/archive/2008/02/20/visual-linq-watch-query-expressions-as-they-happen.aspx

3

Il a tort.

Les deux blocs de code sont identiques.
En fait, si vous n'utilisez pas subResult n'importe où ailleurs, ils devraient compiler exactement le même IL en mode release.

1

LINQ est implémenté en tant que méthodes d'extension sur IEnumerable. Vous pouvez envisager de travailler avec des requêtes LINQ en deux étapes. D'abord, vous définissez la requête, puis vous effectuez une itération sur la requête. Jusqu'à la deuxième étape où vous itérez réellement la requête, elle n'a pas encore été exécutée.

Les deux exemples sont fonctionnellement équivalents et aucun d'entre eux seront réellement exécuter la requête jusqu'à ce que vous itérer sur le résultat, à quel point les deux opérateurs de requête LINQ (Where et OrderBy) exécutera le retour de leur résultat dénombrable approprié à l'autre et, en fin de compte , au code effectuant l'itération.

0

exécution différée et les méthodes d'extension sont des concepts totalement séparés.

Sans syntaxe de la méthode d'extension:

var result = System.Linq.Enumerable.Where(
    myList, a => a.CustomerName == "Bob"); 

Avec des méthodes d'extension, myList semble avoir une méthode Where (il n'a pas bien).

var result = myList.Where(a => a.CustomerName == "Bob"); 
Questions connexes