CodeGym /Kurslar /C# SELF /Hadisəyə abunəlik və handler-lərin yaradılması

Hadisəyə abunəlik və handler-lərin yaradılması

C# SELF
Səviyyə , Dərs
Mövcuddur

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
event Action
ev += Handler;
void Handler() { ... }
event Action<int>
ev += (x) => { ... };
void Handler(int x) { ... }
event EventHandler
ev += Handler;
void Handler(object s, EventArgs e) { ... }
event EventHandler<CustomArgs>
ev += Handler;
void Handler(object s, CustomArgs e) { ... }

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.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Bir neçə abunəçi ilə hadisə
Bir neçə abunəçi ilə hadisə
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION