Partager via


Déclencher et consommer des événements

Cet article explique comment utiliser des événements dans .NET à l’aide du EventHandler délégué, du EventHandler<TEventArgs> délégué et d’un délégué personnalisé, avec des exemples d’événements avec et sans données.

Prerequisites

Familiarisez-vous avec les concepts de l’article Événements .

Déclencher un événement sans données

Ces étapes créent une Counter classe qui déclenche un ThresholdReached événement lorsqu’un total en cours d’exécution atteint ou dépasse un seuil.

  1. Déclarez l’événement à l’aide du EventHandler délégué.

    Utilisez cette option EventHandler lorsque votre événement ne transmet pas de données au gestionnaire :

    public event EventHandler? ThresholdReached;
    
    Public Event ThresholdReached As EventHandler
    
  2. Ajoutez une protected virtual méthode (Protected Overridable en Visual Basic) pour déclencher l’événement.

    Ce modèle permet aux classes dérivées de remplacer le comportement de déclenchement d’événements sans appeler directement le délégué. En C#, utilisez l’opérateur conditionnel Null (?.) pour vous protéger contre aucun abonné (en Visual Basic, RaiseEvent gère cela automatiquement) :

    protected virtual void OnThresholdReached(EventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }
    
    Protected Overridable Sub OnThresholdReached(e As EventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub
    
  3. Appelez la méthode raise lorsque la condition est remplie.

    Passez Empty, puisque cet événement ne contient pas de données :

    if (_total >= _threshold)
    {
        OnThresholdReached(EventArgs.Empty);
    }
    
    If (_total >= _threshold) Then
        OnThresholdReached(EventArgs.Empty)
    End If
    
  4. Abonnez-vous à l’événement à l’aide de l’opérateur += (en Visual Basic) AddHandler:

    c.ThresholdReached += c_ThresholdReached;
    
    AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
    
  5. Définissez la méthode du gestionnaire d’événements.

    Sa signature doit correspondre au EventHandler délégué : le premier paramètre est la source d’événement et le second est EventArgs:

    static void c_ThresholdReached(object? sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
        Environment.Exit(0);
    }
    
    Sub c_ThresholdReached(sender As Object, e As EventArgs)
        Console.WriteLine("The threshold was reached.")
        Environment.Exit(0)
    End Sub
    

L’exemple suivant montre l’implémentation complète :

class EventNoData
{
    static void Main()
    {
        Counter c = new(new Random().Next(10));
        c.ThresholdReached += c_ThresholdReached;

        Console.WriteLine("press 'a' key to increase total");
        while (Console.ReadKey(true).KeyChar == 'a')
        {
            Console.WriteLine("adding one");
            c.Add(1);
        }
    }

    static void c_ThresholdReached(object? sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
        Environment.Exit(0);
    }
}

class Counter(int passedThreshold)
{
    private readonly int _threshold = passedThreshold;
    private int _total;

    public void Add(int x)
    {
        _total += x;
        if (_total >= _threshold)
        {
            OnThresholdReached(EventArgs.Empty);
        }
    }

    protected virtual void OnThresholdReached(EventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }

    public event EventHandler? ThresholdReached;
}
Module EventNoData

    Sub Main()
        Dim c As New Counter(New Random().Next(10))
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        Console.WriteLine("press 'a' key to increase total")
        While Console.ReadKey(True).KeyChar = "a"
            Console.WriteLine("adding one")
            c.Add(1)
        End While
    End Sub

    Sub c_ThresholdReached(sender As Object, e As EventArgs)
        Console.WriteLine("The threshold was reached.")
        Environment.Exit(0)
    End Sub
End Module

Class Counter
    Private ReadOnly _threshold As Integer
    Private _total As Integer

    Public Sub New(passedThreshold As Integer)
        _threshold = passedThreshold
    End Sub

    Public Sub Add(x As Integer)
        _total += x
        If (_total >= _threshold) Then
            OnThresholdReached(EventArgs.Empty)
        End If
    End Sub

    Protected Overridable Sub OnThresholdReached(e As EventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    Public Event ThresholdReached As EventHandler
End Class

Déclencher un événement avec des données

Ces étapes étendent l’exemple précédent Counter pour déclencher un événement incluant des données , la valeur de seuil et le moment où elles ont été atteintes.

  1. Définissez une classe de données d’événement qui hérite de EventArgs.

    Ajoutez des propriétés pour chaque élément de données que vous souhaitez transmettre au gestionnaire :

    public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }
    
    Class ThresholdReachedEventArgs
        Inherits EventArgs
    
        Public Property Threshold As Integer
        Public Property TimeReached As Date
    End Class
    
  2. Déclarez l’événement à l’aide du EventHandler<TEventArgs> délégué, en passant votre classe de données d’événement en tant qu’argument de type :

    public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;
    
    Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)
    
  3. Ajoutez une protected virtual méthode (Protected Overridable en Visual Basic) pour déclencher l’événement.

    Ce modèle permet aux classes dérivées de remplacer le comportement de déclenchement d’événements sans appeler directement le délégué. En C#, utilisez l’opérateur conditionnel Null (?.) pour vous protéger contre aucun abonné (en Visual Basic, RaiseEvent gère cela automatiquement) :

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }
    
    Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub
    
  4. Remplissez l’objet de données d’événement et appelez la méthode raise lorsque la condition est remplie :

    if (_total >= _threshold)
    {
        ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
        args.Threshold = _threshold;
        args.TimeReached = DateTime.Now;
        OnThresholdReached(args);
    }
    
    If (_total >= _threshold) Then
        Dim args As New ThresholdReachedEventArgs With {
            .Threshold = _threshold,
            .TimeReached = Date.Now
        }
        OnThresholdReached(args)
    End If
    
  5. Abonnez-vous à l’événement à l’aide de l’opérateur += (en Visual Basic) AddHandler:

    c.ThresholdReached += c_ThresholdReached;
    
    AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
    
  6. Définissez le gestionnaire d’événements.

    Le deuxième type de paramètre est ThresholdReachedEventArgs au lieu de EventArgs, ce qui permet au gestionnaire de lire les données d’événement :

    static void c_ThresholdReached(object? sender, ThresholdReachedEventArgs e)
    {
        Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
        Environment.Exit(0);
    }
    
    Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
        Environment.Exit(0)
    End Sub
    

L’exemple suivant montre l’implémentation complète :

class EventWithData
{
    static void Main()
    {
        CounterWithData c = new(new Random().Next(10));
        c.ThresholdReached += c_ThresholdReached;

        Console.WriteLine("press 'a' key to increase total");
        while (Console.ReadKey(true).KeyChar == 'a')
        {
            Console.WriteLine("adding one");
            c.Add(1);
        }
    }

    static void c_ThresholdReached(object? sender, ThresholdReachedEventArgs e)
    {
        Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
        Environment.Exit(0);
    }
}

class CounterWithData(int passedThreshold)
{
    private readonly int _threshold = passedThreshold;
    private int _total;

    public void Add(int x)
    {
        _total += x;
        if (_total >= _threshold)
        {
            ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
            args.Threshold = _threshold;
            args.TimeReached = DateTime.Now;
            OnThresholdReached(args);
        }
    }

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }

    public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;
}

public class ThresholdReachedEventArgs : EventArgs
{
    public int Threshold { get; set; }
    public DateTime TimeReached { get; set; }
}
Module EventWithData

    Sub Main()
        Dim c As New CounterWithData(New Random().Next(10))
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        Console.WriteLine("press 'a' key to increase total")
        While Console.ReadKey(True).KeyChar = "a"
            Console.WriteLine("adding one")
            c.Add(1)
        End While
    End Sub

    Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
        Environment.Exit(0)
    End Sub
End Module

Class CounterWithData
    Private ReadOnly _threshold As Integer
    Private _total As Integer

    Public Sub New(passedThreshold As Integer)
        _threshold = passedThreshold
    End Sub

    Public Sub Add(x As Integer)
        _total += x
        If (_total >= _threshold) Then
            Dim args As New ThresholdReachedEventArgs With {
                .Threshold = _threshold,
                .TimeReached = Date.Now
            }
            OnThresholdReached(args)
        End If
    End Sub

    Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)
End Class

Class ThresholdReachedEventArgs
    Inherits EventArgs

    Public Property Threshold As Integer
    Public Property TimeReached As Date
End Class

Déclarer un délégué personnalisé pour un événement

Déclarez un délégué personnalisé uniquement dans des scénarios rares, comme rendre votre classe disponible pour le code hérité qui ne peut pas utiliser de génériques. Pour la plupart des cas, utilisez EventHandler<TEventArgs> comme indiqué dans la section précédente.

  1. Déclarez le type de délégué personnalisé.

    La signature de délégué doit correspondre à la signature du gestionnaire d’événements : deux paramètres : la source d’événement (object ; en Visual Basic Object) et la classe de données d’événement :

    public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
    
    Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)
    
  2. Déclarez l’événement à l’aide de votre type délégué personnalisé au lieu de EventHandler<TEventArgs>:

    public event ThresholdReachedEventHandler? ThresholdReached;
    
    Public Event ThresholdReached As ThresholdReachedEventHandler
    
  3. Ajoutez une protected virtual méthode (Protected Overridable en Visual Basic) pour déclencher l’événement.

    En C#, utilisez l’opérateur conditionnel Null (?.) pour vous protéger contre aucun abonné (en Visual Basic, RaiseEvent gère cela automatiquement) :

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }
    
    Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub
    
  4. Remplissez l’objet de données d’événement et appelez la méthode raise lorsque la condition est remplie :

    if (_total >= _threshold)
    {
        ThresholdReachedEventArgs args = new();
        args.Threshold = _threshold;
        args.TimeReached = DateTime.Now;
        OnThresholdReached(args);
    }
    
    If (_total >= _threshold) Then
        Dim args As New ThresholdReachedEventArgs With {
            .Threshold = _threshold,
            .TimeReached = Date.Now
        }
        OnThresholdReached(args)
    End If
    
  5. Abonnez-vous à l’événement à l’aide de l’opérateur += (en Visual Basic) AddHandler:

    c.ThresholdReached += c_ThresholdReached;
    
    AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
    
  6. Définissez le gestionnaire d’événements.

    La signature du gestionnaire doit correspondre au délégué personnalisé ,object pour l’expéditeur et votre classe de données d’événement pour le deuxième paramètre :

    static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
    {
        Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
        Environment.Exit(0);
    }
    
    Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
        Environment.Exit(0)
    End Sub
    

L’exemple suivant montre l’implémentation complète :

class EventWithDelegate
{
    static void Main()
    {
        CounterWithDelegate c = new(new Random().Next(10));
        c.ThresholdReached += c_ThresholdReached;

        Console.WriteLine("press 'a' key to increase total");
        while (Console.ReadKey(true).KeyChar == 'a')
        {
            Console.WriteLine("adding one");
            c.Add(1);
        }
    }

    static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
    {
        Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
        Environment.Exit(0);
    }
}

class CounterWithDelegate(int passedThreshold)
{
    private readonly int _threshold = passedThreshold;
    private int _total;

    public void Add(int x)
    {
        _total += x;
        if (_total >= _threshold)
        {
            ThresholdReachedEventArgs args = new();
            args.Threshold = _threshold;
            args.TimeReached = DateTime.Now;
            OnThresholdReached(args);
        }
    }

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        ThresholdReached?.Invoke(this, e);
    }

    public event ThresholdReachedEventHandler? ThresholdReached;
}

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Module EventWithDelegate

    Sub Main()
        Dim c As New CounterWithDelegate(New Random().Next(10))
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        Console.WriteLine("press 'a' key to increase total")
        While Console.ReadKey(True).KeyChar = "a"
            Console.WriteLine("adding one")
            c.Add(1)
        End While
    End Sub

    Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
        Environment.Exit(0)
    End Sub
End Module

Class CounterWithDelegate
    Private ReadOnly _threshold As Integer
    Private _total As Integer

    Public Sub New(passedThreshold As Integer)
        _threshold = passedThreshold
    End Sub

    Public Sub Add(x As Integer)
        _total += x
        If (_total >= _threshold) Then
            Dim args As New ThresholdReachedEventArgs With {
                .Threshold = _threshold,
                .TimeReached = Date.Now
            }
            OnThresholdReached(args)
        End If
    End Sub

    Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    Public Event ThresholdReached As ThresholdReachedEventHandler
End Class

Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)