Saya menjawab pertanyaan tentang kemungkinan penutupan (secara sah) memperpanjang masa hidup objek ketika saya bertemu dengan beberapa kode-gen yang sangat aneh pada bagian dari kompiler C # (4.0 jika itu penting).
Repro terpendek yang bisa saya temukan adalah sebagai berikut:
- Buat lambda yang menangkap lokal sambil memanggil metode statis dari tipe yang memuatnya.
- Tetapkan referensi-delegasi yang dihasilkan ke bidang instance dari objek yang memuat.
Hasil: Kompilator membuat objek-penutup yang mereferensikan objek yang membuat lambda, jika tidak memiliki alasan untuk - target 'dalam' dari delegasi adalah metode statis , dan anggota instance objek-pembuatan-lambda tidak perlu menjadi (dan tidak) disentuh saat delegasi dieksekusi. Secara efektif, kompilator bertindak seperti pemrogram menangkap this
tanpa alasan.
class Foo
{
private Action _field;
public void InstanceMethod()
{
var capturedVariable = Math.Pow(42, 1);
_field = () => StaticMethod(capturedVariable);
}
private static void StaticMethod(double arg) { }
}
Kode yang dihasilkan dari rilis build (didekompilasi menjadi 'lebih sederhana' C #) terlihat seperti ini:
public void InstanceMethod()
{
<>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.<>4__this = this; // What's this doing here?
CS$<>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
this._field = new Action(CS$<>8__locals2.<InstanceMethod>b__0);
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public Foo <>4__this; // Never read, only written to.
public double capturedVariable;
// Methods
public void <InstanceMethod>b__0()
{
Foo.StaticMethod(this.capturedVariable);
}
}
Amati bahwa <>4__this
bidang objek penutupan diisi dengan referensi objek tetapi tidak pernah dibaca (tidak ada alasan).
Jadi apa yang terjadi disini? Apakah spesifikasi bahasa memungkinkan untuk itu? Apakah ini bug / keanehan kompilator atau adakah alasan bagus (bahwa saya jelas hilang) untuk closure untuk mereferensikan objek? Ini membuat saya cemas karena ini terlihat seperti resep bagi programmer yang senang menutup (seperti saya) untuk tanpa disadari memperkenalkan kebocoran memori yang aneh (bayangkan jika delegasi digunakan sebagai penangan acara) ke dalam program.
this
.