Seperti yang Anda lihat pada kode di bawah ini, saya telah mendeklarasikan Action<>
objek sebagai variabel.
Adakah yang bisa memberi tahu saya mengapa delegasi metode tindakan ini berperilaku seperti metode statis?
Mengapa itu kembali true
dalam kode berikut?
Kode:
public static void Main(string[] args)
{
Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };
Console.WriteLine(actionMethod.Method.IsStatic);
Console.Read();
}
Keluaran:
c#
.net
reflection
lambda
nunu
sumber
sumber
static
metode tersebut.Ildasm
sangat berguna untuk memahami apa yang sebenarnya terjadi, saya cenderung menggunakanIL
tab dariLINQPad
untuk memeriksa sampel kecil.IL
tabLINQPad
dan menyimpulkan C #. Beberapa opsi untuk mendapatkan C # yang sebenarnya setara dari output yang dikompilasi akan menggunakanILSpy
atauReflector
pada rakitan yang dikompilasi, Anda kemungkinan besar perlu menonaktifkan beberapa opsi yang akan mencoba menampilkan lambda dan bukan kelas yang dihasilkan kompilator."Metode tindakan" bersifat statis hanya sebagai efek samping dari implementasi. Ini adalah kasus metode anonim tanpa variabel yang ditangkap. Karena tidak ada variabel yang ditangkap, metode ini tidak memiliki persyaratan umur tambahan selain variabel lokal pada umumnya. Jika ia mereferensikan variabel lokal lain, masa pakainya meluas ke masa pakai variabel lain tersebut (lihat bagian L.1.7, Variabel lokal , dan bagian N.15.5.1, Variabel luar yang ditangkap , dalam spesifikasi C # 5.0).
Perhatikan bahwa spesifikasi C # hanya berbicara tentang metode anonim yang diubah menjadi "pohon ekspresi", bukan "kelas anonim". Sementara pohon ekspresi dapat direpresentasikan sebagai kelas C # tambahan, misalnya, dalam kompilator Microsoft, implementasi ini tidak diperlukan (seperti yang diakui oleh bagian M.5.3 dalam spesifikasi C # 5.0). Oleh karena itu, tidak ditentukan apakah fungsi anonim itu statis atau tidak. Selain itu, bagian K.6 daun lebih terbuka untuk detail pohon ekspresi.
sumber
Perilaku cache delegasi diubah di Roslyn. Sebelumnya, seperti yang dinyatakan, setiap ekspresi lambda yang tidak menangkap variabel dikompilasi menjadi
static
metode di situs panggilan. Roslyn mengubah perilaku ini. Sekarang, lambda apa pun, yang menangkap variabel atau tidak, diubah menjadi kelas tampilan:Diberikan contoh ini:
Keluaran kompiler asli:
Roslyn:
Delegasi perubahan perilaku cache di Roslyn berbicara tentang mengapa perubahan ini dibuat.
sumber
Mulai C # 6, ini akan selalu default ke metode instance sekarang, dan tidak akan pernah statis (jadi
actionMethod.Method.IsStatic
akan selalu salah).Lihat di sini: Mengapa lambda tanpa tangkapan berubah dari statis di C # 5 menjadi metode instance di C # 6?
dan di sini: Perbedaan dalam evaluasi ekspresi lambda statis kompiler CSC dan Roslyn?
sumber
Metode ini tidak memiliki penutupan dan juga mereferensikan metode statis itu sendiri (Console.WriteLine), jadi saya berharap itu menjadi statis. Metode tersebut akan mendeklarasikan tipe anonim yang melingkupi penutupan, tetapi dalam hal ini tidak diperlukan.
sumber