Una volta compilato, c'è una differenza tra:
delegate { x = 0; }
e
() => { x = 0 }
?
Una volta compilato, c'è una differenza tra:
delegate { x = 0; }
e
() => { x = 0 }
?
Risposte:
Risposta breve: no.
Risposta più lunga che potrebbe non essere pertinente:
Func
o Action
) otterrai un delegato anonimo.Modifica: ecco alcuni link per le espressioni.
Mi piace la risposta di Amy, ma ho pensato di essere pedante. La domanda dice "Una volta compilata", il che suggerisce che entrambe le espressioni sono state compilate. Come hanno potuto compilare entrambi, ma con uno convertito in un delegato e uno in un albero delle espressioni? È complicato: devi usare un'altra funzione di metodi anonimi; l'unico che non è condiviso dalle espressioni lambda. Se si specifica un metodo anonimo senza specificare un elenco di parametri a tutti che è compatibile con qualsiasi tipo delegato tornare vuoto e senza out
parametri. Forti di questa conoscenza, dovremmo essere in grado di costruire due sovraccarichi per rendere le espressioni completamente inequivocabili ma molto diverse.
Ma il disastro colpisce! Almeno con C # 3.0, non è possibile convertire un'espressione lambda con un corpo di blocco in un'espressione, né è possibile convertire un'espressione lambda con un'assegnazione nel corpo (anche se viene utilizzata come valore di ritorno). Questo può cambiare con C # 4.0 e .NET 4.0, che consentono di esprimere di più in un albero delle espressioni. Quindi, in altre parole, con gli esempi forniti da MojoFilter, i due saranno quasi sempre convertiti nella stessa cosa. (Maggiori dettagli in un minuto.)
Possiamo usare il trucco dei parametri delegati se cambiamo un po 'i corpi però:
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...");
}
}
Ma aspetta! Possiamo distinguere tra i due anche senza usare alberi delle espressioni, se siamo abbastanza furbi. L'esempio seguente utilizza le regole di risoluzione del sovraccarico (e il trucco di corrispondenza del delegato anonimo) ...
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; } );
}
}
Ahia. Ricorda i bambini, ogni volta che sovraccarichi un metodo ereditato da una classe base, un gattino inizia a piangere.
delegate { ... }
è lo stesso di - quest'ultimo è compatibile solo con un tipo delegato senza parametri. delegate() { ... }
Nei due esempi sopra non c'è differenza, zero.
L'espressione:
() => { x = 0 }
è un'espressione Lambda con corpo dell'istruzione, quindi non può essere compilata come un albero delle espressioni. In realtà non si compila nemmeno perché ha bisogno di un punto e virgola dopo 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B ha ragione. Si noti che possono esserci vantaggi nell'uso degli alberi delle espressioni. LINQ to SQL esaminerà l'albero delle espressioni e lo convertirà in SQL.
Puoi anche giocare brutti scherzi con i lama e gli alberi delle espressioni per passare efficacemente i nomi dei membri della classe a un framework in modo sicuro dal refactoring. Moq ne è un esempio.
C'è una differenza
Esempio:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
E sostituisco con lambda: (errore)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Alcune basi qui.
Questo è un metodo anonimo
(string testString) => { Console.WriteLine(testString); };
Poiché i metodi anonimi non hanno nomi, abbiamo bisogno di un delegato in cui possiamo assegnare entrambi questi metodi o espressioni. per esempio
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
Lo stesso con l'espressione lambda. Di solito abbiamo bisogno di un delegato per usarli
s => s.Age > someValue && s.Age < someValue // will return true/false
Possiamo usare un delegato di funzione per usare questa espressione.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);