Voici la réponse au précédent Quizz.
Pour la version simple:
var q = from v1 in values1 from v2 in values2 select v1 + v2;
Voici maintenant la syntaxe équivalente en C# 'classique':
var q = values1.SelectMany(v1 => values2.Select(v2 => v1 + v2));
Je vais redéfinir ma question: quelle est la portée d'un paramètre d'expression lambda ? En plus clair, quand j'écris 'source.Where(s => ...).Select(s2 => ...)' d'où puis-je appeler 's' ?
's' est un paramètre de méthode (certes anonyme dans notre cas) et n'est donc utilisable qu'à l'intérieur du 'Where'.
Beaucoup de méthodes d'extension de Linq renvoient leur paramètre d'entrée tel quel (OrderBy, Where) et nous font croire que le paramètre est utilisable tout au long de la requête alors qu'il est passé de méthode en méthode.
var q = from c in customers where c.City == "Paris" select c.CustomerID;
var q = customers.Where(c => c.City == "Paris").Select(c2 => c2.CustomerID);
D'autres méthodes d'extension de Linq ne renvoient pas le paramètre d'entrée (Select, GroupBy) et cassent ainsi la visibilité des paramètres précédemment définis.
Un problème apparait donc : comment définir deux sources (v1 et v2 dans notre exemple) en rendant chacune d'elle accessible dans les méthodes suivantes ?
Je rappelle la déclaration précédente: un paramètre de méthode a une portée limité à la méthode elle-même. Le seul moyen est donc de créer un second 'Select' à l'intérieur d'un premier et non en enchaînant une séquence de méthodes.
La syntaxe Linq est évidemment beaucoup plus simple à lire en nous faisant croire que les 'from' sont en séquence alors qu'ils s'imbriquent. On pourrait symboliquement ajouter les parenthèses suivantes:
var q = from v1 in values1 ( from v2 in values2 select v1 + v2 );
Cette compréhension ne vous est bien évidemment pas nécessaire pour utiliser Linq mais risque de le devenir si vous voulez écrire vos propres méthodes d'extension.