315 votes

Expressions Lambda en C# : Pourquoi les utiliser ?

J'ai lu rapidement les Expression Lambda Microsoft la documentation.

Ce type d'exemple m'a cependant aidé à mieux comprendre :

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

Pourtant, je ne comprends pas pourquoi il s'agit d'une telle innovation. C'est juste une méthode qui meurt lorsque la "variable méthode" se termine, n'est-ce pas ? Pourquoi devrais-je l'utiliser au lieu d'une vraie méthode ?

5 votes

Pour ceux d'entre vous qui arrivent sur cette page et qui ne savent pas ce qu'est un delegate est en C#, je vous conseille vivement de lire ce document. b lire le reste de cette page : stackoverflow.com/questions/2082615/

284voto

Neil Williams Points 6446

Expressions lambda constituent une syntaxe plus simple pour les délégués anonymes et peuvent être utilisés partout où un délégué anonyme peut être utilisé. Cependant, l'inverse n'est pas vrai ; les expressions lambda peuvent être converties en arbres d'expression, ce qui permet de réaliser une grande partie de la magie de LINQ to SQL.

Voici un exemple de LINQ to Objects Nous avons utilisé des délégués anonymes, puis des expressions lambda pour montrer à quel point elles sont plus faciles à comprendre :

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

Les expressions lambda et les délégués anonymes présentent un avantage par rapport à l'écriture d'une fonction distincte : ils mettent en œuvre la fonction fermetures qui peut vous permettre de transmettre l'état local à la fonction sans ajouter de paramètres à la fonction ou la création d'objets à usage unique.

Arbres d'expression sont une nouvelle fonctionnalité très puissante de C# 3.0 qui permet à une API d'examiner la structure d'une expression au lieu d'obtenir simplement une référence à une méthode qui peut être exécutée. Une API n'a qu'à transformer un paramètre délégué en un paramètre Expression<T> et le compilateur générera un arbre d'expression à partir d'une lambda au lieu d'un délégué anonyme :

void Example(Predicate<int> aDelegate);

appelé comme :

Example(x => x > 5);

devient :

void Example(Expression<Predicate<int>> expressionTree);

Ce dernier se verra transmettre une représentation de la arbre syntaxique abstrait qui décrit l'expression x > 5 . LINQ to SQL s'appuie sur ce comportement pour transformer les expressions C# en expressions SQL souhaitées pour le filtrage, l'ordonnancement, etc. du côté du serveur.

1 votes

Sans les fermetures, vous pouvez utiliser des méthodes statiques comme rappels, mais vous devez toujours définir ces méthodes dans une classe, ce qui augmente presque certainement la portée de ces méthodes au-delà de l'usage prévu.

138voto

Joseph Daigle Points 16429

Les fonctions et expressions anonymes sont utiles pour les méthodes ponctuelles qui ne nécessitent pas le travail supplémentaire requis pour créer une méthode complète.

Prenons l'exemple suivant :

 List<string> people = new List<string> { "name1", "name2", "joe", "another name", "etc" };
 string person = people.Find(person => person.Contains("Joe"));

par rapport à

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

Ils sont fonctionnellement équivalents.

9 votes

Comment la méthode Find() aurait-elle été définie pour traiter cette expression lambda ?

3 votes

Predicate<T> est ce que la méthode Find attend.

1 votes

Comme mon expression lambda correspond au contrat de Predicate<T>, la méthode Find() l'accepte.

84voto

agnieszka Points 3668

Je les ai trouvés utiles dans une situation où je voulais déclarer un gestionnaire pour l'événement d'un certain contrôle, en utilisant un autre contrôle. Pour le faire normalement, vous auriez dû stocker les références des contrôles dans des champs de la classe afin de pouvoir les utiliser dans une méthode différente de celle dans laquelle ils ont été créés.

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

grâce aux expressions lambda, vous pouvez l'utiliser comme suit :

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}

C'est beaucoup plus facile.

0 votes

Dans le premier exemple, pourquoi ne pas faire passer l'expéditeur et obtenir la valeur ?

0 votes

@Andrew : Dans cet exemple simple, il n'est pas nécessaire d'utiliser l'expéditeur, car il n'y a qu'un seul composant en question et l'utilisation directe du champ permet d'économiser une distribution, ce qui améliore la clarté. Dans un scénario réel, je préférerais personnellement utiliser l'expéditeur à la place. En général, j'utilise un seul gestionnaire d'événements pour plusieurs événements, si possible, et je dois donc identifier l'expéditeur réel.

35voto

FlySwat Points 61945

Lambda a nettoyé la syntaxe des délégués anonymes de C# 2.0... par exemple

Strings.Find(s => s == "hello");

Il a été réalisé en C# 2.0 comme suit :

Strings.Find(delegate(String s) { return s == "hello"; });

Fonctionnellement, ils font exactement la même chose, c'est juste une syntaxe beaucoup plus concise.

3 votes

Ils ne sont pas tout à fait la même chose - comme le souligne @Neil Williams, vous pouvez extraire l'AST d'un lambda en utilisant des arbres d'expression, alors que les méthodes anonymes ne peuvent pas être utilisées de la même manière.

0 votes

C'est l'un des nombreux autres avantages de lambda. Il aide à comprendre le code mieux que les méthodes anonymes. Ce n'est certainement pas l'intention de créer des lambdas, mais ce sont des scénarios où ils peuvent être utilisés plus souvent.

28voto

Scott Dorman Points 25000

Ce n'est qu'une façon d'utiliser une expression lambda. Vous pouvez utiliser une expression lambda n'importe où vous pouvez utiliser un délégué. Cela vous permet de faire des choses comme ceci :

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

Ce code recherchera dans la liste une entrée correspondant au mot "hello". L'autre façon de procéder consiste à passer un délégué à la méthode Find, comme ceci :

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

EDITAR :

En C# 2.0, cela pouvait se faire en utilisant la syntaxe des délégués anonymes :

  strings.Find(delegate(String s) { return s == "hello"; });

Lambda a considérablement nettoyé cette syntaxe.

2 votes

@Jonathan Holland : Merci pour la modification et l'ajout de la syntaxe du délégué anonyme. Cela complète bien l'exemple.

0 votes

Qu'est-ce qu'un délégué anonyme ? //sorry i am new to c#

1 votes

@HackerMan, considérez un délégué anonyme comme une fonction qui n'a pas de "nom". Vous définissez toujours une fonction, qui peut avoir une entrée et une sortie, mais puisque c'est un nom, vous ne pouvez pas vous y référer directement. Dans le code ci-dessus, vous définissez une méthode (qui prend un élément string et renvoie un bool ) en tant que paramètre de la fonction Find elle-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X