Comment LINQ fonctionne-t-il en interne?

J’aime utiliser LINQ sur .net, mais je me demande comment cela fonctionne en interne?

Est-ce que quelqu’un le sait?

Thks.

Il est plus logique de poser des questions sur un aspect particulier de LINQ. C’est un peu comme demander “comment fonctionne Windows” sinon.

Les éléments clés de LINQ sont pour moi, du sharepoint vue de C #:

  • Arbres d’expression. Ce sont des représentations de code en tant que données. Par exemple, un arbre d’expression peut représenter la notion de “prendre un paramètre de chaîne, appeler la propriété Longueur et renvoyer le résultat”. Le fait que ceux-ci existent en tant que données plutôt qu’en tant que code compilé signifie que les fournisseurs LINQ tels que LINQ to SQL peuvent les parsingr et les convertir en SQL.
  • Expressions lambda Ce sont des expressions comme ceci:

    x => x * 2 (int x, int y) => x * y () => { Console.WriteLine("Block"); Console.WriteLine("Lambda"); } 

    Les expressions lambda sont converties en delegates ou en arborescences d’expression .

  • Types anonymes Ce sont des expressions comme ceci:

     new { X=10, Y=20 } 

    Celles-ci sont toujours typées statiquement, c’est juste que le compilateur génère un type immuable pour vous avec les propriétés X et Y Celles-ci sont généralement utilisées avec var qui permet d’inférer le type d’une variable locale à partir de son expression d’initialisation.

  • Expressions de requête. Ce sont des expressions comme ceci:

     from person in people where person.Age < 18 select person.Name 

    Ceux-ci sont traduits par le compilateur C # en C # 3.0 "normal" (c'est-à-dire un formulaire qui n'utilise pas les expressions de requête). La résolution de surcharge, etc. est appliquée par la suite, ce qui est absolument essentiel pour pouvoir utiliser la même syntaxe de requête avec plusieurs types de données, sans que le compilateur ait connaissance de types tels que Queryable. L'expression ci-dessus serait traduite en:

     people.Where(person => person.Age < 18) .Select(person => person.Name) 
  • Méthodes d'extension Ce sont des méthodes statiques qui peuvent être utilisées comme s'il s'agissait de méthodes d'instance du type du premier paramètre. Par exemple, une méthode d'extension comme celle-ci:

     public static int CountAsciiDigits(this ssortingng text) { return text.Count(letter => letter >= '0' && letter <= '9'); } 

    peut alors être utilisé comme ceci:

     ssortingng foo = "123abc456"; int count = foo.CountAsciiDigits(); 

    Notez que l'implémentation de CountAsciiDigits utilise une autre méthode d'extension, Enumerable.Count() .

C'est la plupart des aspects linguistiques pertinents. Ensuite, il y a les implémentations des opérateurs de requête standard, dans les fournisseurs LINQ tels que LINQ to Objects et LINQ to SQL etc. J'ai une présentation sur la façon simple d'implémenter LINQ to Objects - c'est la page "Talks" du C # dans le site web de Depth.

La façon dont les fournisseurs tels que LINQ to SQL fonctionnent est généralement via la classe Queryable . Fondamentalement, ils traduisent des arborescences d’expressions dans d’autres formats de requête, puis créent des objects appropriés avec les résultats de l’exécution de ces requêtes hors processus.

Cela couvre-t-il tout ce qui vous intéresse? S'il y a quelque chose en particulier que vous voulez toujours savoir, modifiez simplement votre question et je vais essayer.

LINQ est essentiellement une combinaison de caractéristiques discrètes C # 3.0 de ceux-ci:

  • inférence de type variable locale
  • propriétés automatiques (non implémentées dans VB 9.0)
  • méthodes d’extension
  • expressions lambda
  • initialiseurs de type anonyme
  • compréhension de la requête

Pour plus d’informations sur le voyage pour s’y rendre (LINQ), voir cette vidéo d’Anders dans LANGNET 2008:

http://download.microsoft.com/download/c/e/5/ce5434ca-4f54-42b1-81ea-7f5a72f3b1dd/1-01%20-%20CSharp3%20-%20Anders%20Hejlsberg.wmv

Dans un simple formulaire, le compilateur prend votre requête de code et la convertit en un tas de classes et d’appels génériques. Sous Linq2Sql, une requête SQL dynamic est construite et exécutée en utilisant DbCommand, DbDataReader, etc.

Disons que vous avez:

 var q = from x in dc.mytable select x; 

il est converti en code suivant:

 IQueryable q = dc.mytable.Select( Expression.Lambda>( exp = Expression.Parameter(typeof(mytable), "x"), new ParameterExpression[] { exp } ) ); 

Beaucoup de génériques, énormes frais généraux.

En gros, linq est un mélange de certaines fonctionnalités de langage (compilateur) et de certaines extensions de framework. Ainsi, lorsque vous écrivez des requêtes linq, elles sont exécutées en utilisant des interfaces appropriées telles que IQuerable. Notez également que le moteur d’exécution n’a pas de rôle dans linq.

Mais il est difficile de rendre justice à linq dans une réponse courte. Je vous recommande de lire un livre pour vous y mettre. Je ne suis pas sûr du livre qui vous raconte les internes de Linq, mais Linq in Action donne un bon coup de main à ce sujet.

J’ai un petit programme C # qui démontre l’implémentation de LINQ en C #.

 class Program { static void Main(ssortingng[] args) { //Eventhough we call the method here, it gets called ONLY when the for loop is executed var Cities = LinQFunction(new List() { "Bangalore", "Mysore", "Coorg", "Tumkur", "Kerala", "TamilNadu" }); //LinQFunction() gets callled now foreach(var city in Cities) { Console.WriteLine(city); } } //This function is called ONLY when the foreach loop iterates and gets the item from the collection static IEnumerable LinQFunction(List cities) { foreach (var item in cities) { //Return each 'item' at a time yield return item; } } } 

Utilisez les points d’arrêt appropriés.