Dies liegt höchstwahrscheinlich daran, dass es keine Schließungen gibt, zum Beispiel:
int age = 25;
Action<string> withClosure = s => Console.WriteLine("My name is {0} and I am {1} years old", s, age);
Action<string> withoutClosure = s => Console.WriteLine("My name is {0}", s);
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
Dies wird false
für withClosure
und true
für ausgegeben withoutClosure
.
Wenn Sie einen Lambda-Ausdruck verwenden, erstellt der Compiler eine kleine Klasse, die Ihre Methode enthält. Dies würde sich wie folgt kompilieren lassen (die tatsächliche Implementierung variiert höchstwahrscheinlich geringfügig):
private class <Main>b__0
{
public int age;
public void withClosure(string s)
{
Console.WriteLine("My name is {0} and I am {1} years old", s, age)
}
}
private static class <Main>b__1
{
public static void withoutClosure(string s)
{
Console.WriteLine("My name is {0}", s)
}
}
public static void Main()
{
var b__0 = new <Main>b__0();
b__0.age = 25;
Action<string> withClosure = b__0.withClosure;
Action<string> withoutClosure = <Main>b__1.withoutClosure;
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
}
Sie können sehen, dass die resultierenden Action<string>
Instanzen tatsächlich auf Methoden für diese generierten Klassen verweisen.
static
Methoden.Ildasm
ist wirklich nützlich, um zu verstehen, was tatsächlich vor sich geht. Ich benutze normalerweise dieIL
Registerkarte vonLINQPad
, um kleine Proben zu untersuchen.IL
RegisterkarteLINQPad
C # verwendet und daraus abgeleitet. Einige Optionen, um das tatsächliche C # -Äquivalent der kompilierten Ausgabe zu erhalten, sind die VerwendungILSpy
oderReflector
die kompilierte Assembly. Sie müssten höchstwahrscheinlich einige Optionen deaktivieren, mit denen versucht wird, die Lambdas und nicht die vom Compiler generierten Klassen anzuzeigen.Die "Aktionsmethode" ist nur als Nebeneffekt der Implementierung statisch. Dies ist ein Fall einer anonymen Methode ohne erfasste Variablen. Da keine erfassten Variablen vorhanden sind, stellt die Methode keine zusätzlichen Anforderungen an die Lebensdauer, die über die für lokale Variablen im Allgemeinen hinausgehen. Wenn auf andere lokale Variablen verwiesen wurde, erstreckt sich seine Lebensdauer auf die Lebensdauer dieser anderen Variablen (siehe Abschnitt L.1.7, Lokale Variablen , und Abschnitt N.15.5.1, Erfasste äußere Variablen , in der C # 5.0-Spezifikation).
Beachten Sie, dass die C # -Spezifikation nur von anonymen Methoden spricht, die in "Ausdrucksbäume" konvertiert werden, nicht von "anonymen Klassen". Während der Ausdrucksbaum beispielsweise im Microsoft-Compiler als zusätzliche C # -Klassen dargestellt werden könnte, ist diese Implementierung nicht erforderlich (wie in Abschnitt M.5.3 in der C # 5.0-Spezifikation bestätigt). Daher ist nicht definiert, ob die anonyme Funktion statisch ist oder nicht. Darüber hinaus lässt Abschnitt K.6 die Details der Expressionsbäume offen.
quelle
Das Caching-Verhalten von Delegierten wurde in Roslyn geändert. Wie bereits erwähnt, wurde zuvor jeder Lambda-Ausdruck, der keine Variablen erfasst hat
static
, an der Aufrufstelle zu einer Methode kompiliert . Roslyn hat dieses Verhalten geändert. Jetzt wird jedes Lambda, das Variablen erfasst oder nicht, in eine Anzeigeklasse umgewandelt:Angesichts dieses Beispiels:
Native Compiler-Ausgabe:
Roslyn:
Änderungen des Caching-Verhaltens von Delegierten in Roslyn sprechen darüber, warum diese Änderung vorgenommen wurde.
quelle
Ab C # 6 werden jetzt immer standardmäßig Instanzmethoden verwendet und sind niemals statisch (also
actionMethod.Method.IsStatic
immer falsch).Siehe hier: Warum wurde ein Lambda ohne Erfassung von einer statischen in C # 5 zu einer Instanzmethode in C # 6 geändert?
und hier: Unterschied in der statischen Lambda-Ausdrucksbewertung von CSC und Roslyn-Compiler?
quelle
Die Methode hat keine Abschlüsse und verweist auch auf eine statische Methode selbst (Console.WriteLine), daher würde ich erwarten, dass sie statisch ist. Die Methode deklariert einen einschließenden anonymen Typ für einen Abschluss, ist jedoch in diesem Fall nicht erforderlich.
quelle