192 votes

mot-clé délégué vs notation lambda

Une fois compilé, existe-t-il une différence entre:

 delegate { x = 0; }
 

et

 () => { x = 0 }
 

?

147voto

David B Points 53123

Réponse courte : non.

Plus de réponse qui peuvent ne pas être pertinentes:

  • Si vous attribuez le lambda d'un type délégué (comme Func ou d'Action), vous obtiendrez un délégué anonyme.
  • Si vous affectez le lambda à un type d'Expression, vous aurez une expression de l'arbre au lieu d'un délégué anonyme. L'expression de l'arbre peut ensuite être compilé pour un délégué anonyme.

Edit: Voici quelques liens pour les Expressions.

  • Système.Linq.De l'Expression.L'Expression(TDelegate) (en cliquant ici).
  • Linq en mémoire avec les délégués (comme Système.Func) utilise le Système.Linq.Énumérable. Linq to SQL (et rien d'autre) avec des expressions utilise le Système.Linq.Queryable. Vérifiez les paramètres de ces méthodes.
  • Une Explication de ScottGu. En un mot, Linq en mémoire produisent une certaine anonyme méthodes pour résoudre votre requête. Linq to SQL va produire une arborescence d'expression que représente la requête, puis de traduire cet arbre en exécutable T-SQL. Linq to entities va produire une arborescence d'expression que représente la requête, puis de traduire cet arbre dans la plate-forme SQL approprié.

128voto

Jon Skeet Points 692016

J'aime bien David réponse, mais je pensais être pédant. La question dit, "une Fois qu'il est compilé" - ce qui suggère que les deux expressions ont été compilées. Comment ont-ils pu compiler, mais avec un être converti en un délégué et un délégué d'une arborescence d'expression? C'est une question difficile - vous devez utiliser une autre caractéristique de méthodes anonymes; le seul qui n'est pas partagée par les expressions lambda. Si vous spécifiez une méthode anonyme sans spécifier une liste de paramètres à tous il est compatible avec tout type de délégué de retour nulle et sans out paramètres. Armés de cette connaissance, nous devrions être en mesure de construire deux surcharges de rendre les expressions sans ambiguïté, mais très différents.

Mais la catastrophe! Au moins avec C# 3.0, vous ne pouvez pas convertir une expression lambda avec un bloc de corps dans une expression - et vous ne pouvez pas convertir une expression lambda avec une affectation dans le corps (même si elle est utilisée comme valeur de retour). Cela pourrait changer avec C# 4.0 et .NET 4.0, qui permettent plus d'être exprimé dans une arborescence d'expression. Donc, en d'autres termes, avec les exemples MojoFilter qui est arrivé à donner, les deux seront presque toujours être converti à la même chose. (Plus de détails dans une minute).

Nous pouvons utiliser le délégué paramètres truc si nous changeons le corps un peu:

using System;
using System.Linq.Expressions;

public class Test
{
    static void Main()
    {
        int x = 0;
        Foo( () => x );
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }

    static void Foo(Expression<Func<int>> func)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

Mais attendez! Nous pouvons distinguer entre les deux, même sans l'aide de l'expression des arbres, si nous sommes assez rusé. L'exemple ci-dessous utilise la résolution de surcharge règles (et le délégué anonyme correspondant truc)...

using System;
using System.Linq.Expressions;

public class Base
{
    public void Foo(Action action)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

public class Derived : Base
{
    public void Foo(Action<int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int x = 0;
        d.Foo( () => { x = 0; } );
        d.Foo( delegate { x = 0; } );
    }
}

Ouch. Rappelez-vous les enfants, à chaque fois que vous la surcharge des méthodes d'une classe de base, un petit chaton se met à pleurer.

4voto

Olmo Points 1928

Dans les deux exemples, il n'y a pas de différence, zéro.

L'expression

 () => { x = 0 }
 

est une expression Lambda avec un corps d'instruction, elle ne peut donc pas être compilée en tant qu'arbre d'expression. En fait, il ne compile même pas, il faut un point-virgule après 0:

 () => { x = 0; } //Lambda statement body 
() => x = 0  // lambda expression body, could be an expression tree.
 

3voto

Daniel Plaisted Points 11183

David B est correcte. Notez qu’il peut y avoir des avantages à utiliser des arborescences d’expression. LINQ to SQL va examiner l’arborescence de l’expression et convertissez-le en SQL.

Vous pouvez également jouer des tours avec des arbres lamdas et d’expression pour transmettre efficacement les noms des membres de la classe à un cadre dans une manière sécurisée de refactorisation. MOQ est un exemple de ceci.

-1voto

Il y a une différence

Exemple :

Et j’ai remplacer par lambda:(error)

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