Prenumerera och avsluta prenumerationen på händelser i C#

Slutförd

Händelser i C# möjliggör kommunikation mellan objekt, vilket gör att en klass eller ett objekt kan meddela andra klasser eller objekt när något av intresse inträffar. Den här utbildningsenheten fokuserar på de praktiska aspekterna av att prenumerera och avprenumerera från händelser, säkerställa effektiv resursanvändning och undvika vanliga fallgropar som minnesläckor.

När du fortsätter att utveckla butiksprogrammet fokuserar ditt team nu på att se till att händelseprenumerationer hanteras effektivt. När en kund till exempel slutför ett köp vill du att lagersystemet ska uppdatera lagernivåerna och försäljningsrapporteringssystemet för att logga transaktionen. Korrekt hantering av händelseprenumerationer säkerställer att dessa processer är effektiva och inte leder till resursläckor eller oväntat beteende.

Prenumerera på händelser

Att prenumerera på en händelse innebär att koppla en metod till händelsen med hjälp av operatorn += . Händelseprenumeration tillåter att metoden anropas när händelsen utlöses.

Exempel: Prenumerera på en händelse

public class Button
{
    public event EventHandler Clicked;

    public void OnClick()
    {
        Clicked?.Invoke(this, EventArgs.Empty);
    }
}

public class Program
{
    public static void Main()
    {
        Button button = new Button();
        button.Clicked += Button_Clicked;

        button.OnClick(); // Output: "Button was clicked!"
    }

    private static void Button_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("Button was clicked!");
    }
}

Observera att den tidigare koden visar hur du prenumererar på en händelse med hjälp av operatorn += . Händelsen Clicked utlöses från OnClick metoden och Button_Clicked metoden hanterar händelsen. Syntaxen ?.Invoke säkerställer att händelsen endast utlöses om det finns prenumeranter.

Avprenumerera från händelser

Att avsluta prenumerationen av en händelse innebär att en metod kopplas bort från händelsen med operatorn -=. Det är viktigt att inte prenumerera på händelser för att förhindra minnesläckage, särskilt när händelseutgivaren har en längre livslängd än prenumeranten.

Exempel: Avprenumerera från en händelse

public class Button
{
    public event EventHandler Clicked;

    public void OnClick()
    {
        Clicked?.Invoke(this, EventArgs.Empty);
    }
}

public class Program
{
    public static void Main()
    {
        Button button = new Button();
        EventHandler handler = Button_Clicked;

        button.Clicked += handler;
        button.Clicked -= handler;

        button.OnClick(); // No output, as the handler was unsubscribed.
    }

    private static void Button_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("Button was clicked!");
    }
}

Undersökningen av den här koden visar hur du avbryter prenumerationen på en händelse med hjälp av operatorn -= . När du har avslutat prenumerationen anropas inte längre händelsehanteraren när händelsen aktiveras.

Hantera prenumerationer dynamiskt

I vissa scenarier måste du dynamiskt lägga till eller ta bort händelsehanterare baserat på specifika villkor. Att ta bort händelsehanterare dynamiskt kan vara användbart för att hantera komplexa arbetsflöden eller se till att endast relevanta hanterare kopplas vid en viss tidpunkt.

Exempel: Dynamisk prenumerationshantering

public class Button
{
    public event EventHandler Clicked;

    public void OnClick()
    {
        Clicked?.Invoke(this, EventArgs.Empty);
    }
}

public class Program
{
    public static void Main()
    {
        Button button = new Button();
        bool isSubscribed = false;

        EventHandler handler = (sender, e) => Console.WriteLine("Dynamic handler executed!");

        if (!isSubscribed)
        {
            button.Clicked += handler;
            isSubscribed = true;
        }

        button.OnClick(); // Output: "Dynamic handler executed!"

        if (isSubscribed)
        {
            button.Clicked -= handler;
            isSubscribed = false;
        }

        button.OnClick(); // No output, as the handler was unsubscribed.
    }
}

I det här exemplet innehåller koden dynamiskt hanterade händelseprenumerationer. Flaggan isSubscribed säkerställer att hanteraren läggs till eller tas bort baserat på specifika villkor.

Undvika minnesläckor

Minnesläckor kan inträffa när händelsehanterare inte avregistreras, särskilt om händelseutgivaren överlever prenumeranten. För att undvika minnesläckor avbryter du alltid prenumerationen på händelser när de inte längre behövs.

Metodtips för att undvika minnesläckor:

  • Använd svaga referenser eller WeakEventManager i scenarier där prenumerantens livslängd är kortare än utgivarens.
  • Avsluta prenumerationen på händelser i metoden för Dispose engångsobjekt.
  • Undvik anonyma metoder eller lambda-uttryck för händelsehanterare om du inte uttryckligen kan avbryta prenumerationen.

Exempel: att avprenumerera på Dispose

public class Subscriber : IDisposable
{
    private readonly Button _button;

    public Subscriber(Button button)
    {
        _button = button;
        _button.Clicked += Button_Clicked;
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("Button clicked!");
    }

    public void Dispose()
    {
        _button.Clicked -= Button_Clicked;
    }
}

I det här kodexemplet visas hur du slutar prenumerera på händelser i Dispose-metoden. Den här metoden säkerställer att händelsehanterare tas bort korrekt, vilket förhindrar minnesläckor när objektet tas bort.

Sammanfattning

Genom att förstå hur du prenumererar och avregistrerar dig från händelser kan du säkerställa effektiv resursanvändning och undvika vanliga fallgropar som minnesläckor. Korrekt händelsehantering är viktigt för att skapa robusta och underhållsbara program.