Jak widać w poniższym kodzie, zadeklarowałem plik Action<>
obiekt jako zmienną.
Czy ktoś mógłby mi powiedzieć, dlaczego ten delegat metody akcji zachowuje się jak metoda statyczna?
Dlaczego powraca true
w poniższym kodzie?
Kod:
public static void Main(string[] args)
{
Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };
Console.WriteLine(actionMethod.Method.IsStatic);
Console.Read();
}
Wynik:
c#
.net
reflection
lambda
nunu
źródło
źródło
static
metod.Ildasm
jest naprawdę przydatny do zrozumienia, co się właściwie dzieje, zwykle używamIL
kartyLINQPad
do badania małych próbek.IL
kartyLINQPad
i wywnioskowałem C #. Niektóre opcje uzyskania rzeczywistego odpowiednika C # skompilowanych danych wyjściowych polegałyby na użyciuILSpy
lubReflector
w skompilowanym zestawie, najprawdopodobniej będziesz musiał wyłączyć niektóre opcje, które będą próbowały wyświetlić lambdy, a nie klasy wygenerowane przez kompilator.„Metoda akcji” jest statyczna tylko jako efekt uboczny implementacji. Jest to przypadek metody anonimowej bez przechwytywanych zmiennych. Ponieważ nie ma zmiennych przechwytywanych, metoda nie ma dodatkowych wymagań dotyczących czasu życia poza ogólnymi wymaganiami dla zmiennych lokalnych. Jeśli odnosił się do innych zmiennych lokalnych, jego czas życia rozciąga się na czas życia tych innych zmiennych (patrz rozdział L.1.7, Zmienne lokalne i rozdział N.15.5.1, Przechwycone zmienne zewnętrzne w specyfikacji C # 5.0).
Zauważ, że specyfikacja C # mówi tylko o anonimowych metodach konwertowanych na „drzewa wyrażeń”, a nie o „klasy anonimowe”. Chociaż drzewo wyrażeń może być reprezentowane jako dodatkowe klasy C #, na przykład w kompilatorze firmy Microsoft, ta implementacja nie jest wymagana (co potwierdza sekcja M.5.3 w specyfikacji C # 5.0). Dlatego nie jest zdefiniowane, czy funkcja anonimowa jest statyczna, czy nie. Co więcej, sekcja K.6 pozostawia wiele otwartości co do szczegółów drzew ekspresji.
źródło
W Roslyn zmieniono zachowanie buforowania delegatów. Wcześniej, jak wspomniano, każde wyrażenie lambda, które nie przechwytuje zmiennych, było kompilowane do pliku
static
metody w miejscu wywołania. Roslyn zmieniła to zachowanie. Teraz każda lambda, która przechwytuje zmienne lub nie, jest przekształcana w klasę wyświetlania:Biorąc pod uwagę ten przykład:
Natywne wyjście kompilatora:
Roslyn:
Delegowanie zmian zachowania buforowania w Roslyn wyjaśnia, dlaczego ta zmiana została wprowadzona.
źródło
Począwszy od C # 6, teraz będzie to zawsze domyślnie metody wystąpienia i nigdy nie będzie statyczne (tak
actionMethod.Method.IsStatic
zawsze będzie miało wartość false).Spójrz tutaj: Dlaczego lambda bez przechwytywania zostało zmienione z metody statycznej w C # 5 na metodę wystąpienia w C # 6?
i tutaj: Różnica w obliczaniu statycznego wyrażenia lambda kompilatora CSC i Roslyn?
źródło
Metoda nie ma domknięć, a także odwołuje się do samej metody statycznej (Console.WriteLine), więc spodziewałbym się, że będzie statyczna. Metoda zadeklaruje otaczający typ anonimowy dla zamknięcia, ale w tym przypadku nie jest to wymagane.
źródło