1. Hadisəyə abunəlik sintaksisi
Təsəvvür edin ki, tapşırıqları idarə edən bir tətbiq var: tapşırıq bitəndə hadisə baş verir və handler, məsələn, bildiriş göndərə, UI-ni yeniləyə və ya log-a məlumat yaza bilər. C# hadisələrə abunə olmağı rahat və təhlükəsiz edir: konkret handler-in konkret hadisəyə reaksiya verdiyini açıq göstərirsiniz.
C#-da hadisəyə abunəlik demək olar ki, özünü partiyaya qonaq kimi əlavə etmək kimidir:
publisher.MyEvent += HandlerMethod;
Burada publisher — hadisəni elan etmiş obyektdir MyEvent, və HandlerMethod — hadisə baş verəndə çağırılacaq metoddur.
Gəlin bunu minimal nümunə kontekstində görək. Fərz edək ki, klik sayını qeyd edən bir tətbiqimiz var:
public class Clicker
{
public event Action Clicked;
public void Click()
{
// Nəsə klikləndi!
Clicked?.Invoke();
}
}
Budur bizim "publisher" hadisəsi Clicked. İndi — handler-ə abunə olaq:
Clicker clicker = new Clicker();
void OnClicked()
{
Console.WriteLine("Düymə basıldı!");
}
clicker.Clicked += OnClicked;
// Kodun bir yerində
clicker.Click();
// → "Düymə basıldı!"
Bu necə işləyir? "Klik" hadisəsinə bizim OnClicked metodunu əlavə etdik və klik hər baş verdikdə o çağırılacaq.
2. Hadisə handler-ləri: növləri və necə elan etmək
Hadisə handler-i — hadisə baş verəndə çağırılacaq metoddur. Onun imzası hadisənin delegate tipinə uyğun olmalıdır. Məsələn, əgər hadisə belə elan edilibsə public event Action Clicked;, o zaman handler parametrsiz və qaytarması olmayan metod olmalıdır.
Action üçün handler
void OnClicked()
{
Console.WriteLine("Hadisə baş verdi (Action)!");
}
Standart EventHandler üçün handler
Ənənəvi yanaşmada EventHandler istifadə edərkən handler iki parametr götürür: göndərən (object sender) və hadisə məlumatları (EventArgs e):
public class Alarm
{
public event EventHandler AlarmRaised;
public void RaiseAlarm()
{
AlarmRaised?.Invoke(this, EventArgs.Empty);
}
}
Alarm alarm = new Alarm();
void AlarmHandler(object sender, EventArgs e)
{
Console.WriteLine("Siqnal işlədi!");
}
alarm.AlarmRaised += AlarmHandler;
alarm.RaiseAlarm();
Anonim metodlar və lambda-ifadələr
C# abunəlik zamanı anonim funksiyalar və lambda-ifadələrdən birbaşa istifadə etməyə imkan verir:
clicker.Clicked += () => Console.WriteLine("Another click!");
Və ya hadisənin arqumentləri varsa, daha mürəkkəb nümunə:
alarm.AlarmRaised += (sender, e) =>
{
Console.WriteLine($"Alarm raised by: {sender}");
};
4. Faydalı nüanslar
Abunəlik və abonelikdən çıxma: vacib nüanslar
Həqiqi həyat — partiyada çoxlu qonaq olduqda və ya kimsə evə getmək istədikdə başlayır. Delegatlarda da eyni: handler əlavə etmək (abunə olmaq) və silmək (abonelikdən çıxmaq) mümkündür:
// Abunəlik
publisher.MyEvent += MyHandler;
// Abonelikdən çıxma (handler artıq lazım olmadıqda)
publisher.MyEvent -= MyHandler;
Niyə bu vacibdir? Xüsusən böyük tətbiqlərdə abonelikdən çıxmazsanız, handler-lər "asılı" qala bilər və garbage collector obyektləri təmizləyə bilməz — nəticədə yaddaş sızması ola bilər.
Bir neçə handler
Bir hadisəyə istənilən sayda handler abunə ola bilər. Onlar əlavə edildiyi ardıcıllıqla çağırılacaqlar.
clicker.Clicked += () => Console.WriteLine("Birinci handler!");
clicker.Clicked += () => Console.WriteLine("İkinci handler!");
clicker.Click();
// → Birinci handler!
// → İkinci handler!
Siz hətta handler-ləri "canlı" olaraq abunə edib çıxara bilərsiniz — bu çevik və rahatdır.
Niyə bu həqiqətən vacibdir: real ssenarilər
- UI (Windows Forms, WPF, WinUI, MAUI): düyməyə klik, mətn sahəsinin dəyişməsi — bunların hamısı hadisələrdir.
- FileSystemWatcher: qovluqda yeni faylın görünməsi barədə bildiriş.
- Asinxron əməliyyatlar: fayl yüklənməsinin tamamlanması, tapşırıqların progress-i.
- Plugin sistemi: ayrıca modullar əsas tətbiqin hadisələrinə abunə olur.
Hadisə modeli genişlənə bilən arxitekturalar qurmağa imkan verir: yeni modullar əlavə edib mövcud hadisələrə abunə ola bilərsiniz, əsas kodu dəyişmədən.
Abunəlik nümunələri
| Hadisə imzası | Abunə nümunəsi | Handler nümunəsi |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
5. Tipik səhvlər və tələfər
Səhv №1: handler imzasının uyğunsuzluğu.
Əgər hadisə belə elan edilibsə event Action<int>, və siz parametrsiz metoda abunə olmağa çalışırsınızsa, compiler xətası verəcək. Həmişə metodun hadisənin tələb etdiyi imzaya uyğun olduğuna əmin olun.
Səhv №2: lambda-larda dəyişənlərin tutulması.
Lambda-ifadə ilə abunəlik zamanı lambda ətraf mühitdən dəyişənləri tuta bilər (bax: mövzu «Bağlanmalar»). Abunəlikdən sonra dəyişən dəyişsə, handler artıq yeni dəyəri görəcək, bu isə gözlənilməz nəticələrə gətirə bilər.
Səhv №3: inisializasiya olunmamış hadisəyə abunəlik.
Əgər hadisə saxlayan obyekt yaradılıb və inisializasiya edilməmişdən əvvəl abunə olursunuzsa, NullReferenceException almaq riski var. Abunə olmamışdan əvvəl obyektin istifadə üçün hazır olduğundan əmin olun.
Səhv №4: eyni handler-in çoxlu abunə edilməsi.
Əgər eyni handler hadisəyə bir neçə dəfə abunə edilibsə, o elə sayda çağırılacaq. Bu bug deyil, hadisələrin işləmə xüsusiyyətidir, amma çox vaxt xoşagəlməz sürpriz olur.
GO TO FULL VERSION