Menu
Coddy logo textTech

Delegaty i zdarzenia

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 43 z 70.

Delegat to typ reprezentujący odwołanie do metody. Możesz myśleć o nim jak o zmiennej przechowującej metodę zamiast danych. Dzięki temu możesz przekazywać metody jako argumenty, przechowywać je w kolekcjach i wywoływać je dynamicznie.

Deklarujesz delegata, określając sygnaturę metody, do której może się odwoływać:

public delegate void Notify(string message);

public class Publisher
{
    public void SendAlert(string msg) => Console.WriteLine("Alert: " + msg);
}

// Użycie
Notify notifier = new Publisher().SendAlert;
notifier("System started");  // Alert: System started

Zdarzenia opierają się na delegatach, aby implementować wzorzec publikuj-subskrybuj. Klasa wywołuje zdarzenie, a inne klasy mogą subskrybować je, aby otrzymywać powiadomienia. Słowo kluczowe event ogranicza sposób użycia delegata — subskrybenci mogą jedynie dodawać lub usuwać procedury obsługi, a nie wywoływać zdarzenia bezpośrednio.

public class Button
{
    public event Action Clicked;
    
    public void Click()
    {
        Clicked?.Invoke();  // Powiadom wszystkich subskrybentów
    }
}

// Subskrybowanie
Button btn = new Button();
btn.Clicked += () => Console.WriteLine("Button was clicked!");
btn.Click();  // Przycisk został kliknięty!

Operator += subskrybuje procedurę obsługi, a -= ją anuluje. Wzorzec ?.Invoke() bezpiecznie wywołuje zdarzenie tylko wtedy, gdy są subskrybenci. Zdarzenia są podstawą aplikacji GUI, silników gier i każdego systemu, w którym obiekty muszą reagować na zmiany bez ścisłego powiązania.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system monitorowania temperatury, który wykorzystuje delegaty i zdarzenia do powiadamiania subskrybentów za każdym razem, gdy zmieni się temperatura. To klasyczny przykład wzorca publikuj-subskrybuj, który zdarzenia umożliwiają w tak elegancki sposób.

Podzielisz kod na dwa pliki:

  • TemperatureMonitor.cs: Utwórz klasę TemperatureMonitor w przestrzeni nazw Monitoring, która będzie pełnić rolę wydawcy. Twój monitor powinien:
    • Mieć prywatne pole do przechowywania bieżącej temperatury
    • Deklarować zdarzenie o nazwie TemperatureChanged z użyciem Action<int>, które jest wywoływane za każdym razem, gdy temperatura zostanie zaktualizowana
    • Mieć właściwość Temperature (int), której setter aktualizuje prywatne pole i wywołuje zdarzenie z nową wartością temperatury
    Pamiętaj, aby użyć wzorca ?.Invoke(), żeby bezpiecznie wywoływać zdarzenie tylko wtedy, gdy są subskrybenci.
  • Program.cs: W głównym pliku utwórz obiekt TemperatureMonitor i zasubskrybuj dwa różne procedury obsługi zdarzeń TemperatureChanged:
    • Jedna procedura obsługi, która wyświetla: Alert: Temperature is now {value} degrees
    • Druga procedura obsługi, która wyświetla: Logged: {value}
    Po zasubskrybowaniu obu procedur obsługi ustaw temperaturę dwukrotnie, używając wartości z wejścia. Za każdym razem, gdy ustawisz temperaturę, obie procedury obsługi powinny zareagować.

Otrzymasz dwa dane wejściowe:

  • Pierwsza wartość temperatury (liczba całkowita)
  • Druga wartość temperatury (liczba całkowita)

Na przykład, jeśli dane wejściowe to 25 i 30, wynik powinien wyglądać następująco:

Alert: Temperature is now 25 degrees
Logged: 25
Alert: Temperature is now 30 degrees
Logged: 30

Zauważ, że ustawienie właściwości Temperature automatycznie powiadamia wszystkich subskrybentów — monitor nie musi wiedzieć, kto nasłuchuje. Na tym polega piękno podejścia sterowanego zdarzeniami!

Spróbuj swoich sił

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // Odczytaj dane wejściowe
        int temp1 = Convert.ToInt32(Console.ReadLine());
        int temp2 = Convert.ToInt32(Console.ReadLine());

        // TODO: Utwórz instancję TemperatureMonitor

        // TODO: Zarejestruj procedurę obsługi, która wypisuje: "Alert: Temperature is now {value} degrees"

        // TODO: Zarejestruj kolejną procedurę obsługi, która wypisuje: "Logged: {value}"

        // TODO: Ustaw temperaturę na temp1

        // TODO: Ustaw temperaturę na temp2
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online