LINQ - Expressions Lambda

Le terme «expression lambda» a dérivé son nom du calcul «lambda» qui à son tour est une notation mathématique appliquée pour définir des fonctions. Les expressions Lambda en tant que partie exécutable d'une équation LINQ traduisent la logique d'une manière au moment de l'exécution afin qu'elle puisse la transmettre facilement à la source de données. Cependant, les expressions lambda ne se limitent pas à rechercher des applications dans LINQ uniquement.

Ces expressions sont exprimées par la syntaxe suivante -

(Input parameters) ⇒ Expression or statement block

Voici un exemple d'expression lambda -

y ⇒ y * y

L'expression ci-dessus spécifie un paramètre nommé y et cette valeur de y est au carré. Cependant, il n'est pas possible d'exécuter une expression lambda sous cette forme. Un exemple d'expression lambda en C # est présenté ci-dessous.

C #

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {

      delegate int del(int i);
      static void Main(string[] args) {

         del myDelegate = y ⇒ y * y;
         int j = myDelegate(5);
         Console.WriteLine(j);
         Console.ReadLine();
      }
   }
}

VB

Module Module1
   Private Delegate Function del(ByVal i As Integer) As Integer
   
   Sub Main(ByVal args As String())
   
      Dim myDelegate As del = Function(y) y * y
      Dim j As Integer = myDelegate(5)
      Console.WriteLine(j)
      Console.ReadLine()
	  
   End Sub
   
End Module

Lorsque le code ci-dessus de C # ou VB est compilé et exécuté, il produit le résultat suivant -

25

Expression Lambda

Comme l'expression dans la syntaxe de l'expression lambda présentée ci-dessus est sur le côté droit, ceux-ci sont également connus sous le nom d'expression lambda.

Lambdas asynchrones

L'expression lambda créée en incorporant un traitement asynchrone à l'aide du mot clé async est connue sous le nom de lambdas asynchrones. Voici un exemple de lambda asynchrone.

Func<Task<string>> getWordAsync = async()⇒ “hello”;

Lambda dans les opérateurs de requête standard

Une expression lambda dans un opérateur de requête est évaluée par le même à la demande et fonctionne en permanence sur chacun des éléments de la séquence d'entrée et non sur la séquence entière. Les développeurs sont autorisés par l'expression Lambda à introduire leur propre logique dans les opérateurs de requête standard. Dans l'exemple ci-dessous, le développeur a utilisé l'opérateur 'Where' pour récupérer les valeurs impaires d'une liste donnée en utilisant une expression lambda.

C #

//Get the average of the odd Fibonacci numbers in the series... 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {     
      static void Main(string[] args) {
      
         int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
         double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
         Console.WriteLine(averageValue);
         Console.ReadLine();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
      Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
	  
      Console.WriteLine(averageValue)
      Console.ReadLine()
	  
   End Sub
   
End Module

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

7.33333333333333

Inférence de type dans Lambda

En C #, l'inférence de type est utilisée de manière pratique dans une variété de situations et cela aussi sans spécifier les types explicitement. Cependant, dans le cas d'une expression lambda, l'inférence de type ne fonctionnera que lorsque chaque type a été spécifié car le compilateur doit être satisfait. Prenons l'exemple suivant.

delegate int Transformer (int i);

Ici, le compilateur utilise l'inférence de type pour tirer parti du fait que x est un entier et cela se fait en examinant le type de paramètre du Transformer.

Portée variable dans l'expression Lambda

Il existe certaines règles lors de l'utilisation de la portée de variable dans une expression lambda, comme les variables initiées dans une expression lambda ne sont pas censées être visibles dans une méthode externe. Il existe également une règle selon laquelle une variable capturée ne doit pas être garbage collection à moins que le délégué qui la référence ne devienne éligible pour l'acte de garbage collection. De plus, il existe une règle qui interdit qu'une instruction return dans une expression lambda provoque le retour d'une méthode englobante.

Voici un exemple pour illustrer la portée de la variable dans une expression lambda.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {
      delegate bool D();
      delegate bool D2(int i);

      class Test {
         D del;
         D2 del2;
			
         public void TestMethod(int input) {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () ⇒ { j = 10; return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) ⇒ { return x == j; };

            // Demonstrate value of j:            
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);        // Invoke the delegate.
            bool boolResult = del();
           
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
         }

         static void Main() {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);
           
            Console.WriteLine(result);

            Console.ReadKey();
         }
      }
   }
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

j = 0
j = 10. b = True
True

Arbre d'expression

Les expressions Lambda sont utilisées dans Expression Treeconstruction largement. Un arbre d'expression donne du code dans une structure de données ressemblant à un arbre dans lequel chaque nœud est lui-même une expression comme un appel de méthode ou peut être une opération binaire comme x <y. Vous trouverez ci-dessous un exemple d'utilisation de l'expression lambda pour la construction d'un arbre d'expression.

Déclaration Lambda

Il y a aussi statement lambdasconsistant en deux ou trois instructions, mais ne sont pas utilisés dans la construction d'arbres d'expression. Une instruction return doit être écrite dans une instruction lambda.

Syntaxe de l'instruction lambda

(params)⇒ {statements}

Exemple d'instruction lambda

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace lambdaexample {
   class Program {
      static void Main(string[] args) {
         int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

         foreach (int i in source.Where(x ⇒ 
            {
               if (x <= 3)
                  return true;
               else if (x >= 7)
                  return true;
               return false;
            }
         ))
        Console.WriteLine(i);
        Console.ReadLine();
      }
   }
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

3
8
1
7
9
2
8

Les lambdas sont utilisés comme arguments dans les requêtes LINQ basées sur des méthodes et ne sont jamais autorisés à avoir une place sur le côté gauche des opérateurs comme is ou astout comme les méthodes anonymes. Bien que les expressions Lambda soient très similaires à des méthodes anonymes, elles ne sont pas du tout limitées à être utilisées en tant que délégués uniquement.

Points à retenir lors de l'utilisation d'expressions lambda

  • Une expression lambda peut renvoyer une valeur et peut avoir des paramètres.

  • Les paramètres peuvent être définis de multiples façons avec une expression lambda.

  • S'il y a une seule instruction dans une expression lambda, il n'est pas nécessaire de placer des accolades alors que s'il y a plusieurs instructions, les accolades ainsi que la valeur de retour sont essentielles à écrire.

  • Avec les expressions lambda, il est possible d'accéder aux variables présentes en dehors du bloc d'expression lambda par une fonctionnalité appelée fermeture. L'utilisation de la fermeture doit être faite avec prudence pour éviter tout problème.

  • Il est impossible d'exécuter un code non sécurisé dans une expression lambda.

  • Les expressions Lambda ne sont pas destinées à être utilisées sur le côté gauche de l'opérateur.