Une fois compilé, y a-t-il une différence entre:
delegate { x = 0; }
et
() => { x = 0 }
?
Une fois compilé, y a-t-il une différence entre:
delegate { x = 0; }
et
() => { x = 0 }
?
Réponses:
Réponse courte: non.
Réponse plus longue qui peut ne pas être pertinente:
Func
ou Action
), vous obtiendrez un délégué anonyme.Edit: Voici quelques liens pour les expressions.
J'aime la réponse d'Amy, mais je pensais que je serais pédante. La question dit: "Une fois compilée" - ce qui suggère que les deux expressions ont été compilées. Comment pourraient-ils tous les deux compiler, mais l'un étant converti en délégué et l'autre en arbre d'expression? C'est une question délicate - vous devez utiliser une autre fonctionnalité des méthodes anonymes; le seul qui n'est pas partagé par les expressions lambda. Si vous spécifiez une méthode anonyme sans spécifier une liste de paramètres du tout , il est compatible avec tout type de délégué retour non avenue et sans aucun out
paramètre. Forts de ces connaissances, nous devrions être capables de construire deux surcharges pour rendre les expressions totalement sans ambiguïté mais très différentes.
Mais la catastrophe frappe! Au moins avec C # 3.0, vous ne pouvez pas convertir une expression lambda avec un corps de bloc en une expression - ni convertir une expression lambda avec une affectation dans le corps (même si elle est utilisée comme valeur de retour). Cela peut changer avec C # 4.0 et .NET 4.0, qui permettent d'exprimer davantage dans une arborescence d'expression. Donc, en d'autres termes, avec les exemples que MojoFilter a donné, les deux seront presque toujours convertis en la même chose. (Plus de détails dans une minute.)
Nous pouvons utiliser l'astuce des paramètres de délégué si nous changeons un peu les corps:
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 différencier les deux même sans utiliser d'arbres d'expression, si nous sommes assez rusés. L'exemple ci-dessous utilise les règles de résolution de surcharge (et l'astuce de correspondance de délégué anonyme) ...
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; } );
}
}
Aie. Rappelez-vous les enfants, chaque fois que vous surchargez une méthode héritée d'une classe de base, un petit chaton se met à pleurer.
delegate { ... }
n'est pas la même chose que delegate() { ... }
- ce dernier n'est compatible qu'avec un type de délégué sans paramètre.
Dans les deux exemples ci-dessus, 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 car il a besoin d'un point-virgule après 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B a raison. Notez qu'il peut y avoir des avantages à utiliser des arbres d'expression. LINQ to SQL examinera l'arborescence des expressions et la convertira en SQL.
Vous pouvez également jouer des tours avec des lamdas et des arbres d'expressions pour transmettre efficacement les noms des membres de la classe à un framework d'une manière sûre pour le refactoring. Moq en est un exemple.
Il existe une différence
Exemple:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Et je remplace par lambda: (erreur)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Quelques notions de base ici.
Ceci est une méthode anonyme
(string testString) => { Console.WriteLine(testString); };
Comme les méthodes anonymes n'ont pas de nom, nous avons besoin d'un délégué dans lequel nous pouvons attribuer ces deux méthodes ou expressions. par exemple
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
Idem avec l'expression lambda. Habituellement, nous avons besoin d'un délégué pour les utiliser
s => s.Age > someValue && s.Age < someValue // will return true/false
Nous pouvons utiliser un délégué func pour utiliser cette expression.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);