Gibt es nach dem Kompilieren einen Unterschied zwischen:
delegate { x = 0; }
und
() => { x = 0 }
?
Gibt es nach dem Kompilieren einen Unterschied zwischen:
delegate { x = 0; }
und
() => { x = 0 }
?
Antworten:
Kurze Antwort: nein.
Längere Antwort, die möglicherweise nicht relevant ist:
Func
oder Action
) zuweisen, erhalten Sie einen anonymen Delegaten.Bearbeiten: Hier sind einige Links für Ausdrücke.
Ich mag Amys Antwort, aber ich dachte, ich wäre pedantisch. Die Frage sagt : „Sobald es kompiliert“ - was darauf schließen lässt , dass beide Ausdrücke haben zusammengestellt. Wie könnten sie beide kompilieren, wobei einer in einen Delegaten und einer in einen Ausdrucksbaum konvertiert wird? Es ist schwierig - Sie müssen eine andere Funktion anonymer Methoden verwenden. die einzige, die nicht von Lambda-Ausdrücken geteilt wird. Wenn Sie eine anonyme Methode angeben , ohne eine Parameterliste Angabe überhaupt ist es kompatibel mit jedem Delegattyp void zurückgibt und ohne out
Parameter. Mit diesem Wissen sollten wir in der Lage sein, zwei Überladungen zu konstruieren, um die Ausdrücke völlig eindeutig, aber sehr unterschiedlich zu machen.
Aber die Katastrophe schlägt zu! Zumindest mit C # 3.0 können Sie einen Lambda-Ausdruck mit einem Blockkörper nicht in einen Ausdruck konvertieren - noch können Sie einen Lambda-Ausdruck mit einer Zuweisung im Körper konvertieren (selbst wenn er als Rückgabewert verwendet wird). Dies kann sich mit C # 4.0 und .NET 4.0 ändern, wodurch mehr in einem Ausdrucksbaum ausgedrückt werden können. Mit anderen Worten, mit den Beispielen, die MojoFilter zufällig gegeben hat, werden die beiden fast immer in dasselbe konvertiert. (Weitere Details in einer Minute.)
Wir können den Trick der Delegate-Parameter verwenden, wenn wir die Körper ein wenig ändern:
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...");
}
}
Aber warte! Wir können zwischen den beiden unterscheiden, auch ohne Ausdrucksbäume zu verwenden, wenn wir schlau genug sind. Im folgenden Beispiel werden die Regeln für die Überlastungsauflösung (und der Trick zum Anpassen anonymer Delegaten) verwendet ...
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; } );
}
}
Autsch. Denken Sie daran, Kinder, jedes Mal, wenn Sie eine von einer Basisklasse geerbte Methode überladen, fängt ein kleines Kätzchen an zu weinen.
delegate { ... }
ist nicht das gleiche wie delegate() { ... }
- letztere nur kompatibel mit einer parameterlos Delegattyp ist.
In den beiden obigen Beispielen gibt es keinen Unterschied, Null.
Der Ausdruck:
() => { x = 0 }
ist ein Lambda-Ausdruck mit Anweisungshauptteil und kann daher nicht als Ausdrucksbaum kompiliert werden. Tatsächlich wird es nicht einmal kompiliert, da es nach 0 ein Semikolon benötigt:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B ist richtig. Beachten Sie, dass die Verwendung von Ausdrucksbäumen Vorteile haben kann. LINQ to SQL untersucht den Ausdrucksbaum und konvertiert ihn in SQL.
Sie können auch Streiche mit Lamdas und Ausdrucksbäumen spielen, um die Namen von Klassenmitgliedern auf refactoring-sichere Weise effektiv an ein Framework zu übergeben. Moq ist ein Beispiel dafür.
Da ist ein Unterschied
Beispiel:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Und ich ersetze durch Lambda: (Fehler)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Einige Grundlagen hier.
Dies ist eine anonyme Methode
(string testString) => { Console.WriteLine(testString); };
Da anonyme Methoden keine Namen haben, benötigen wir einen Delegaten, in dem wir beide Methoden oder Ausdrücke zuweisen können. z.B
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
Gleiches gilt für den Lambda-Ausdruck. Normalerweise brauchen wir einen Delegierten, um sie zu benutzen
s => s.Age > someValue && s.Age < someValue // will return true/false
Wir können einen func-Delegaten verwenden, um diesen Ausdruck zu verwenden.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);