Saya memahami tujuan acara, terutama dalam konteks membuat antarmuka pengguna. Saya pikir ini adalah prototipe untuk membuat acara:
public void EventName(object sender, EventArgs e);
Apa yang dilakukan oleh penangan acara, mengapa mereka dibutuhkan, dan bagaimana cara membuatnya?
c#
.net
events
event-handling
Levi Campbell
sumber
sumber
Jawaban:
Untuk memahami event handler, Anda perlu memahami delegasi . Di C # , Anda bisa menganggap delegasi sebagai penunjuk (atau referensi) ke suatu metode. Ini berguna karena pointer dapat diedarkan sebagai nilai.
Konsep sentral dari delegasi adalah tanda tangannya, atau bentuknya. Yaitu (1) jenis kembali dan (2) argumen input. Misalnya, jika kita membuat delegasi
void MyDelegate(object sender, EventArgs e)
, itu hanya bisa menunjuk ke metode yang kembalivoid
, dan mengambilobject
danEventArgs
. Jenisnya seperti lubang persegi dan pasak persegi. Jadi kami mengatakan metode ini memiliki tanda tangan atau bentuk yang sama dengan delegasi.Jadi mengetahui cara membuat referensi ke suatu metode, mari kita pikirkan tentang tujuan acara: kami ingin menyebabkan beberapa kode dieksekusi ketika sesuatu terjadi di tempat lain dalam sistem - atau "menangani acara". Untuk melakukan ini, kami membuat metode khusus untuk kode yang ingin kami jalankan. Perekat antara acara dan metode yang akan dieksekusi adalah delegasi. Acara harus secara internal menyimpan "daftar" pointer ke metode untuk memanggil ketika acara dinaikkan. * Tentu saja, untuk dapat memanggil metode, kita perlu tahu argumen apa yang harus dilalui untuk itu! Kami menggunakan delegasi sebagai "kontrak" antara acara dan semua metode khusus yang akan dipanggil.
Jadi default
EventHandler
(dan banyak yang seperti itu) mewakili bentuk metode tertentu (sekali lagi, void / object-EventArgs). Ketika Anda mendeklarasikan suatu peristiwa, Anda mengatakan bentuk metode (EventHandler) mana yang akan dipanggil oleh acara, dengan menentukan delegasi:(* Ini adalah kunci untuk peristiwa dalam .NET dan menghilangkan "sihir" - suatu peristiwa benar-benar, di bawah selimut, hanya daftar metode dari "bentuk" yang sama. Daftar ini disimpan di tempat acara tersebut berlangsung. Ketika acara "dinaikkan", itu benar-benar hanya "pergi melalui daftar metode ini dan memanggil masing-masing, menggunakan nilai-nilai ini sebagai parameter". Menetapkan event handler hanya lebih cantik, cara lebih mudah untuk menambahkan metode Anda ke daftar metode ini disebut).
sumber
C # tahu dua istilah,
delegate
danevent
. Mari kita mulai dengan yang pertama.Melimpahkan
A
delegate
adalah referensi ke suatu metode. Sama seperti Anda dapat membuat referensi ke sebuah instance:Anda dapat menggunakan delegasi untuk membuat referensi ke metode:
Sekarang Anda memiliki referensi ini ke suatu metode, Anda dapat memanggil metode tersebut melalui referensi:
Tetapi mengapa Anda mau? Anda juga bisa
myFactory.GetInstance()
langsung menelepon . Dalam hal ini Anda bisa. Namun, ada banyak kasus untuk dipikirkan di mana Anda tidak ingin seluruh aplikasi memiliki pengetahuanmyFactory
atau panggilanmyFactory.GetInstance()
langsung.Salah satu yang jelas adalah jika Anda ingin dapat menggantikan
myFactory.GetInstance()
menjadimyOfflineFakeFactory.GetInstance()
dari satu tempat pusat (alias pola metode pabrik ).Pola metode pabrik
Jadi, jika Anda memiliki
TheOtherClass
kelas dan perlu menggunakanmyFactory.GetInstance()
, ini adalah bagaimana kode akan terlihat seperti tanpa delegasi (Anda harus memberiTheOtherClass
tahu tentang jenis AndamyFactory
):Jika Anda akan menggunakan delegasi, Anda tidak perlu mengekspos jenis pabrik saya:
Dengan demikian, Anda dapat memberikan delegasi ke beberapa kelas lain untuk digunakan, tanpa memaparkan tipe Anda kepada mereka. Satu-satunya hal yang Anda perlihatkan adalah tanda tangan dari metode Anda (berapa banyak parameter yang Anda miliki dan semacamnya).
"Tanda tangan metode saya", di mana saya mendengar itu sebelumnya? O ya, antarmuka !!! antarmuka menggambarkan tanda tangan seluruh kelas. Pikirkan delegasi sebagai menggambarkan tanda tangan hanya satu metode!
Perbedaan besar lainnya antara antarmuka dan delegasi adalah bahwa ketika Anda menulis kelas Anda, Anda tidak perlu mengatakan kepada C # "metode ini mengimplementasikan tipe delegasi itu". Dengan antarmuka, Anda perlu mengatakan "kelas ini mengimplementasikan jenis antarmuka".
Selanjutnya, referensi delegasi dapat (dengan beberapa batasan, lihat di bawah) referensi beberapa metode (dipanggil
MulticastDelegate
). Ini berarti bahwa ketika Anda memanggil delegasi, beberapa metode yang dilampirkan secara eksplisit akan dieksekusi. Referensi objek selalu hanya bisa merujuk ke satu objek.Batasan untuk a
MulticastDelegate
adalah bahwa tanda tangan (metode / delegasi) tidak boleh memiliki nilai pengembalian (void
) dan kata kunciout
danref
tidak digunakan dalam tanda tangan. Jelas, Anda tidak dapat memanggil dua metode yang mengembalikan nomor dan mengharapkan mereka untuk mengembalikan nomor yang sama. Setelah tanda tangan dipatuhi, delegasi secara otomatis aMulticastDelegate
.Peristiwa
Acara hanyalah properti (seperti get; set; properti ke instance field) yang mengekspos berlangganan ke delegasi dari objek lain. Namun, properti ini tidak mendukung get; set ;. Sebaliknya, mereka mendukung add; menghapus;
Jadi, Anda dapat memiliki:
Penggunaan di UI (WinForms, WPF, UWP, dan sebagainya)
Jadi, sekarang kita tahu bahwa seorang delegasi adalah referensi ke suatu metode dan bahwa kita dapat memiliki acara untuk memberi tahu dunia bahwa mereka dapat memberi kita metode mereka untuk dirujuk dari delegasi kita, dan kita adalah tombol UI, lalu: kita dapat bertanya kepada siapa saja yang tertarik apakah saya diklik, untuk mendaftarkan metode mereka kepada kami (melalui acara yang kami paparkan). Kita dapat menggunakan semua metode yang diberikan kepada kita dan merujuknya oleh delegasi kita. Dan kemudian, kita akan menunggu dan menunggu .... sampai seorang pengguna datang dan mengklik tombol itu, maka kita akan memiliki cukup alasan untuk memohon delegasi. Dan karena delegasi merujuk semua metode yang diberikan kepada kami, semua metode itu akan dipanggil. Kami tidak tahu apa yang dilakukan metode-metode itu, kami juga tidak tahu kelas mana yang mengimplementasikan metode-metode itu. Yang kami pedulikan hanyalah seseorang tertarik pada kami diklik,
Jawa
Bahasa seperti Java tidak memiliki delegasi. Mereka menggunakan antarmuka sebagai gantinya. Cara mereka melakukannya adalah dengan meminta siapa saja yang tertarik pada 'kami diklik', untuk mengimplementasikan antarmuka tertentu (dengan metode tertentu yang dapat kita panggil), lalu berikan kami seluruh contoh yang mengimplementasikan antarmuka. Kami menyimpan daftar semua objek yang mengimplementasikan antarmuka ini dan dapat memanggil 'metode tertentu yang dapat kami panggil' setiap kali kami diklik.
sumber
event
hanyalah gula sintaks, tidak lebih.Itu sebenarnya adalah deklarasi untuk pengendali event - metode yang akan dipanggil ketika sebuah event dipecat. Untuk membuat acara, Anda akan menulis sesuatu seperti ini:
Dan kemudian Anda dapat berlangganan ke acara seperti ini:
Dengan OnMyEvent () didefinisikan seperti ini:
Setiap kali
Foo
api matiMyEvent
, makaOnMyEvent
pawang Anda akan dipanggil.Anda tidak selalu harus menggunakan instance
EventArgs
sebagai parameter kedua. Jika Anda ingin memasukkan informasi tambahan, Anda dapat menggunakan kelas yang berasal dariEventArgs
(EventArgs
adalah basis dengan konvensi). Misalnya, jika Anda melihat beberapa peristiwa yang ditentukanControl
dalam WinForms, atauFrameworkElement
di WPF, Anda dapat melihat contoh peristiwa yang meneruskan informasi tambahan ke penangan peristiwa.sumber
OnXXX
pola penamaan untuk pengendali acara Anda. (Dengan bodohnya, OnXXX dianggap berarti 'menangani XXX' di MFC, dan 'naikkan XXX' di .net, dan sekarang artinya tidak jelas dan membingungkan - lihat posting ini untuk detailnya ). Nama yang dipilih adalahRaiseXXX
untuk meningkatkan acara, danHandleXXX
atauSender_XXX
untuk untuk penangan acara.Berikut adalah contoh kode yang dapat membantu:
sumber
OnMaximum?.Invoke(this,new MyEventArgs("you've entered..."));
Hanya untuk menambah jawaban hebat yang ada di sini - membangun kode pada yang diterima, yang menggunakan
delegate void MyEventHandler(string foo)
...Karena kompiler mengetahui tipe delegasi dari acara SomethingHappened , ini:
Sepenuhnya setara dengan:
Dan penangan juga bisa tidak terdaftar dengan
-=
seperti ini:Demi kelengkapan, meningkatkan acara dapat dilakukan seperti ini, hanya di kelas yang memiliki acara:
Salinan thread-lokal dari handler diperlukan untuk memastikan doa aman - jika tidak, thread dapat dibatalkan dan membatalkan registrasi handler terakhir untuk acara segera setelah kami memeriksa apakah itu
null
, dan kami akan bersenang-senang diNullReferenceException
sana. .C # 6 memperkenalkan tangan pendek yang bagus untuk pola ini. Ini menggunakan operator propagasi nol.
sumber
Pemahaman saya tentang peristiwa tersebut adalah;
Melimpahkan:
Variabel untuk menampung referensi ke metode / metode yang akan dieksekusi. Ini memungkinkan untuk menyebarkan metode seperti variabel.
Langkah-langkah untuk membuat dan memanggil acara:
Acara ini adalah turunan dari delegasi
Karena suatu kejadian adalah turunan dari delegasi, maka kita harus terlebih dahulu mendefinisikan delegasi.
Tetapkan metode / metode yang akan dieksekusi ketika acara dipecat ( Memanggil delegasi )
Api acara ( Panggil delegasi )
Contoh:
sumber
penerbit: di mana peristiwa itu terjadi. Penerbit harus menentukan delegasi mana yang digunakan kelas dan menghasilkan argumen yang diperlukan, meneruskan argumen itu dan dirinya sendiri ke delegasi.
pelanggan: di mana respons terjadi. Pelanggan harus menentukan metode untuk merespons acara. Metode-metode ini harus menggunakan jenis argumen yang sama dengan delegasi. Pelanggan kemudian menambahkan metode ini ke delegasi penerbit.
Oleh karena itu, ketika acara terjadi di penerbit, delegasi akan menerima beberapa argumen acara (data, dll), tetapi penerbit tidak tahu apa yang akan terjadi dengan semua data ini. Pelanggan dapat membuat metode di kelas mereka sendiri untuk merespons acara di kelas penerbit, sehingga pelanggan dapat menanggapi acara penerbit.
sumber
sumber
Saya setuju dengan KE50 kecuali bahwa saya melihat kata kunci 'acara' sebagai alias untuk 'ActionCollection' karena acara tersebut memiliki koleksi tindakan yang harus dilakukan (mis. Delegasi).
sumber
Jawaban teknis yang luar biasa di pos! Secara teknis saya tidak punya apa-apa untuk ditambahkan.
Salah satu alasan utama mengapa fitur baru muncul dalam bahasa dan perangkat lunak secara umum adalah pemasaran atau politik perusahaan! :-) Ini tidak boleh kurang dari perkiraan!
Saya pikir ini berlaku juga untuk delegasi dan acara tertentu! saya menemukan mereka berguna dan menambah nilai ke bahasa C #, tetapi di sisi lain bahasa Java memutuskan untuk tidak menggunakannya! mereka memutuskan bahwa apa pun yang Anda selesaikan dengan delegasi Anda sudah dapat menyelesaikan dengan fitur yang ada dari bahasa yaitu antarmuka misalnya
Sekarang sekitar tahun 2001 Microsoft merilis .NET framework dan bahasa C # sebagai solusi pesaing untuk Java, jadi ada baiknya untuk memiliki FITUR BARU yang tidak dimiliki Java.
sumber
Baru-baru ini saya membuat contoh cara menggunakan acara di c #, dan mempostingnya di blog saya. Saya mencoba membuatnya sejelas mungkin, dengan contoh yang sangat sederhana. Jika itu dapat membantu siapa pun, ini dia: http://www.konsfik.com/using-events-in-csharp/
Ini termasuk deskripsi dan kode sumber (dengan banyak komentar), dan terutama berfokus pada penggunaan acara dan penangan acara yang tepat (seperti template).
Beberapa poin utama adalah:
Acara seperti "sub-tipe delegasi", hanya lebih terbatas (dengan cara yang baik). Bahkan deklarasi acara selalu menyertakan delegasi (EventHandlers adalah tipe delegasi).
Penangan Kejadian adalah tipe khusus delegasi (Anda mungkin menganggapnya sebagai templat), yang memaksa pengguna untuk membuat acara yang memiliki "tanda tangan" tertentu. Tanda tangan dalam format: (pengirim objek, eventArgs eventarguments).
Anda dapat membuat sub-kelas Anda sendiri dari EventArgs, untuk memasukkan segala jenis informasi yang perlu disampaikan oleh acara tersebut. Tidak perlu menggunakan EventHandlers saat menggunakan acara. Anda dapat melewati mereka sepenuhnya dan menggunakan jenis delegasi Anda sendiri di tempat mereka.
Salah satu perbedaan utama antara menggunakan acara dan delegasi, adalah bahwa peristiwa hanya dapat dipanggil dari dalam kelas tempat mereka dideklarasikan, meskipun mereka dapat dinyatakan sebagai publik. Ini adalah perbedaan yang sangat penting, karena memungkinkan acara Anda diekspos sehingga mereka "terhubung" ke metode eksternal, sementara pada saat yang sama mereka dilindungi dari "penyalahgunaan eksternal".
sumber
Hal lain yang perlu diketahui tentang , dalam beberapa kasus, Anda harus menggunakan Delegasi / Acara ketika Anda membutuhkan kopling tingkat rendah !
Jika Anda ingin menggunakan komponen di beberapa tempat dalam aplikasi , Anda perlu membuat komponen dengan kopling level rendah dan LOGIC khusus yang tidak dikhawatirkan harus didelegasikan ke luar. komponen Anda! Ini memastikan bahwa Anda memiliki sistem yang dipisahkan dan kode pembersih.
Pada prinsip SOLID ini adalah " D ", ( D prinsip inversi dependensi).
Juga dikenal sebagai " IoC ", Inversion of control .
Anda dapat membuat " IoC " dengan Acara, Delegasi, dan DI (Injeksi Ketergantungan).
Sangat mudah untuk mengakses metode di kelas anak. Tetapi lebih sulit untuk mengakses metode di kelas induk dari anak. Anda harus memberikan referensi orang tua kepada anak tersebut! (atau gunakan DI dengan Antarmuka)
Delegasi / Acara memungkinkan kita untuk berkomunikasi dari anak ke orang tua tanpa referensi!
Dalam diagram ini di atas, saya tidak menggunakan Delegasi / Peristiwa dan komponen induk B harus memiliki referensi dari komponen induk A untuk menjalankan logika bisnis yang tidak peduli dalam metode A. (kopling tingkat tinggi)
Dengan pendekatan ini, saya harus meletakkan semua referensi dari semua komponen yang menggunakan komponen B! :(
Dalam diagram ini di atas, saya menggunakan Delegasi / Peristiwa dan komponen B tidak harus diketahui A. (kopling level rendah)
Dan Anda dapat menggunakan komponen B Anda di mana saja di aplikasi Anda !
sumber