Apakah mungkin untuk berhenti berlangganan metode anonim dari suatu peristiwa?
Jika saya berlangganan acara seperti ini:
void MyMethod()
{
Console.WriteLine("I did it!");
}
MyEvent += MyMethod;
Saya dapat berhenti berlangganan seperti ini:
MyEvent -= MyMethod;
Tetapi jika saya berlangganan menggunakan metode anonim:
MyEvent += delegate(){Console.WriteLine("I did it!");};
apakah mungkin untuk berhenti berlangganan metode anonim ini? Jika ya, bagaimana caranya?
Jawaban:
Simpan saja referensi ke delegasi sekitar.
sumber
Salah satu teknik adalah mendeklarasikan variabel untuk menyimpan metode anonim yang kemudian akan tersedia di dalam metode anonim itu sendiri. Ini berhasil bagi saya karena perilaku yang diinginkan adalah berhenti berlangganan setelah acara ditangani.
Contoh:
sumber
Dari memori, spesifikasi secara eksplisit tidak menjamin perilaku dengan cara apa pun ketika menyangkut kesetaraan delegasi yang dibuat dengan metode anonim.
Jika Anda harus berhenti berlangganan, Anda harus menggunakan metode "normal" atau mempertahankan delegasi di tempat lain sehingga Anda dapat berhenti berlangganan dengan delegasi yang sama persis seperti yang Anda gunakan untuk berlangganan.
sumber
In 3.0 dapat disingkat menjadi:
sumber
Karena fitur fungsi lokal C # 7.0 telah dirilis, pendekatan yang disarankan oleh Jc menjadi sangat rapi.
Jadi, jujur, Anda tidak memiliki fungsi anonim sebagai variabel di sini. Tapi saya kira motivasi untuk menggunakannya dalam kasus Anda dapat diterapkan pada fungsi lokal.
sumber
Alih-alih menyimpan referensi untuk delegasi apa pun, Anda dapat mengatur kelas Anda untuk memberikan daftar doa acara kembali ke pemanggil. Pada dasarnya Anda dapat menulis sesuatu seperti ini (dengan asumsi bahwa MyEvent dideklarasikan di dalam MyClass):
Jadi, Anda dapat mengakses seluruh daftar doa dari luar MyClass dan berhenti berlangganan penangan yang Anda inginkan. Misalnya:
Saya sudah menulis posting lengkap tentang teknik ini di sini .
sumber
Jenis pendekatan lumpuh:
Ini mungkin tidak bekerja atau metode yang paling efisien, tetapi harus menyelesaikan pekerjaan.
sumber
Jika Anda ingin dapat mengendalikan berhenti berlangganan maka Anda harus pergi rute yang ditunjukkan dalam jawaban yang Anda terima. Namun, jika Anda hanya khawatir tentang membersihkan referensi ketika kelas berlangganan Anda keluar dari ruang lingkup, maka ada solusi lain (sedikit berbelit-belit) yang melibatkan menggunakan referensi lemah. Saya baru saja memposting pertanyaan dan jawaban tentang topik ini.
sumber
Satu solusi sederhana:
cukup kirimkan variabel eventhandle sebagai parameter ke dirinya sendiri. Acara jika Anda memiliki kasus bahwa Anda tidak dapat mengakses variabel yang dibuat asli karena multithreading, Anda dapat menggunakan ini:
sumber
MyEvent -= myEventHandlerInstance;
dijalankan? Jika memungkinkan, Anda akan mengalami kesalahan. Tetapi saya tidak yakin apakah itu masalahnya.jika Anda ingin merujuk ke beberapa objek dengan delegasi ini, mungkin Anda dapat menggunakan Delegate.CreateDelegate (Tipe, Target objek, MethodInfo methodInfo) .net menganggap delegasi sama dengan target dan methodInfo
sumber
Jika cara terbaik adalah dengan menyimpan referensi pada eventHandler berlangganan, ini dapat dicapai dengan menggunakan Kamus.
Dalam contoh ini, saya harus menggunakan metode anonim untuk memasukkan parameter mergeColumn untuk satu set DataGridViews.
Menggunakan metode MergeColumn dengan mengaktifkan parameter yang disetel ke true memungkinkan acara saat menggunakannya dengan false menonaktifkannya.
sumber