Apakah event handler menghentikan pengumpulan sampah?

183

Jika saya memiliki kode berikut:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

Apakah pClass akan menjadi sampah yang dikumpulkan? Atau akankah ia tetap menembaki acara-acaranya setiap kali terjadi? Apakah saya perlu melakukan yang berikut untuk memungkinkan pengumpulan sampah?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;
Tandai Ingram
sumber
11
Saya akan menyarankan sementara kepada pembaca yang tertarik pada pertanyaan ini bahwa mungkin ada baiknya membiasakan diri dengan peristiwa ringan / pola acara yang lemah, yang JANGAN mencegah pengumpulan sampah terjadi. Bootstrap SO yang bagus untuk topik ini adalah stackoverflow.com/questions/185931/…
fostandy
20
Catatan untuk anak cucu: mengatur referensi ke nol cukup menunda pengumpul sampah dengan menambah satu baris ruang lingkup referensi. .NET bukan VB6.
John Saunders

Jawaban:

207

Untuk pertanyaan spesifik "Apakah pClass akan dikumpulkan menjadi sampah": langganan acara tidak berpengaruh pada pengumpulan pClass (sebagai penerbit).

Untuk GC secara umum (khususnya, target): tergantung apakah MyFunction statis atau berbasis instance.

Seorang delegasi (seperti berlangganan acara) ke metode instance menyertakan referensi ke instance tersebut. Jadi ya, berlangganan acara akan mencegah GC. Namun, begitu objek mempublikasikan acara (pClass di atas) memenuhi syarat untuk koleksi, ini tidak lagi menjadi masalah.

Perhatikan bahwa ini satu arah; yaitu jika kita memiliki:

publisher.SomeEvent += target.SomeHandler;

maka "penerbit" akan membuat "target" tetap hidup, tetapi "target" tidak akan membuat "publisher" tetap hidup.

Jadi tidak: jika pClass akan dikumpulkan, tidak perlu berhenti berlangganan pendengar. Namun, jika pClass berumur panjang (lebih lama dari instance dengan MyFunction), maka pClass dapat membuat instance itu tetap hidup, jadi akan perlu untuk berhenti berlangganan jika Anda ingin target dikumpulkan.

Peristiwa statis, bagaimanapun, karena alasan ini, sangat berbahaya ketika digunakan dengan handler berbasis instance.

Marc Gravell
sumber
6
Nah, jika pertanyaannya adalah "apakah pClass akan dikumpulkan menjadi sampah", maka jawabannya "itu tergantung apakah ..." tidak benar-benar benar. Itu tidak tergantung pada apa pun, seperti yang dicatat oleh Marc sendiri lebih jauh.
Tor Haugen
@ Tor - cukup adil - saya akan mengklarifikasi
Marc Gravell
Meskipun delegasi berlangganan acara hanya menunjukkan satu arah, pelanggan yang memiliki niat untuk berhenti berlangganan dari suatu acara ketika dilakukan dengan itu akan memerlukan beberapa bentuk referensi ke penerbit. Bisa jadi WeakReference, dan dalam beberapa kasus itu mungkin ide yang bagus, tetapi sesering mungkin itu bukan yang kuat.
supercat
Sebuah jawaban yang bagus karena itu juga menjawab sebagian dari pertanyaan (yang tidak ditanyakan): penerbit akan menghentikan pelanggan dari menjadi GC.
Bob Sammers
Ya, dan seperti yang dikatakan @BobSammers, Ini bisa benar-benar menjadi masalah jika turunan jangka pendek, seperti Formulir / Jendela, berlangganan layanan seumur hidup seperti Singleton yang menyediakan data misalnya: Singleton kemudian menyimpan referensi , dan benda-benda itu sebelumnya disimpan dalam ingatan bahkan ketika kita berpikir benda-benda itu diturunkan! Jadi berhati-hatilah saat menggunakan Acara. Kami disalahgunakan dengan acara untuk perangkat lunak besar kami, dan sangat sulit untuk menyelesaikannya setelah itu.
Elo
9

Ya, pClass akan menjadi sampah yang dikumpulkan. Langganan acara tidak menyiratkan bahwa ada referensi ke pClass.

Jika tidak, Anda tidak perlu melepaskan pawang agar pClass dikumpulkan menjadi sampah.

Tor Haugen
sumber
8

Saat sepotong memori tidak lagi direferensikan itu menjadi kandidat untuk pengumpulan sampah. Ketika instance kelas Anda keluar dari ruang lingkup, itu tidak lagi dirujuk oleh program Anda. Tidak lagi digunakan dan karena itu dapat dikumpulkan dengan aman.

Jika Anda tidak yakin apakah sesuatu akan dikumpulkan tanyakan pada diri Anda pertanyaan berikut: apakah masih ada referensi untuk itu? Penangan event direferensikan oleh instance objek, bukan sebaliknya.

laneaneoo
sumber
0

pClassakan menjadi sampah yang dikumpulkan. Namun, jika potongan kode di atas berada di dalam kelas lain, turunan dari kelas itu mungkin tidak dihapus jika Anda tidak diatur pClasske null.

Arav
sumber