« Event » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
(Aucune différence)
|
Dernière version du 4 octobre 2018 à 14:50
Utilisation
Program est abonné à l'évènement MonEvent.
Lorsque MaClasse lance l'évènement MonEvent, la méthode maClasse_MonEvent de Program sera exécutée.
class Program { static void Main(string[] args) { var maClasse = new MaClasse(); maClasse.MonEvent += new EventHandler<MonEventArgs>(maClasse_MonEvent); // délégué anonyme (_sender, _e) = (object sender, MonEventArgs e) maClasse.MonEvent += (_sender, _e) => { Console.WriteLine(_e.Message); }; maClasse.LancerEvenement(); } static void maClasse_MonEvent(object sender, MonEventArgs e) { Console.WriteLine(e.Message); } } public class MaClasse { public event EventHandler<MonEventArgs> MonEvent; // permet au code extérieur à la classe de lancer l’événement. public void LancerEvenement() { OnMonEvent("message"); } // déclarer cette méthode protected pour que les classes dérivées puissent lancer l’événement // et virtual pour que les classes dérivées puissent modifier le lancement de l’événement. protected virtual void OnMonEvent(string message) { // Nouvelle méthode avec l'opérateur conditionnel null MonEvent?.Invoke(this, new MonEventArgs() { Message = message }); // Ancienne méthode // Make a temporary copy of the event to avoid possibility of a race // condition. If the last subscriber unsubscribes immediately after the // null check and before the event is raised. var handler = MonEvent; if (handler != null) { handler(this, new MonEventArgs() { Message = message }); } } } public class MonEventArgs : EventArgs { public string Message { get; set; } } |
Héritage
Un événement n'est accessible que depuis sa classe, quelque soit son modificateur d'accès, car l'EventHandler est toujours déclaré private.
public event EventHandler MonEvent; // la déclaration précédente correspond en fait à private EventHandler monEventDelegate; public event EventHandler MonEvent { add { monEventDelegate += value; } remove { monEventDelegate -= value; } } MonEvent(this, EventArgs.Empty); // l'appel précédent correspond en fait à monEventDelegate(this, EventArgs.Empty); |
Solution de contournement : utiliser une méthode protected qui encapsule le lancement de l’événement.
Supprimer tous les EventHandlers associés à un event
pour ce faire il faut intercepter l'ajout d'EventHandlers et les stocker en vue de la suppression.
private ArrayList _eventHandlersList = new ArrayList(); private EventHandler _monEventHandler; public event EventHandler MonEvent { add { _monEventHandler += value; // on intercepte l'ajout d'EventHandler et on en profite pour l'enregistrer dans _eventHandlersList _eventHandlersList.Add(value); } remove { _monEventHandler -= value; _eventHandlersList.Remove(value); } } public void RemoveAllEventHandlers() { foreach (EventHandler eventHandler in _eventHandlersList) { _monEventHandler -= eventHandler; } delegates.Clear(); } public void Méthode() { MonEvent += new EventHandler(...); MonEvent += new EventHandler(...); // on supprime tous les EventHandler associés à MonEvent RemoveAllEventHandlers(); } |
Event vs Delegate
L'Event est un wrapper autour de Delegate.
Event ne permet pas d'assignation direct d'un delegate, mais plutôt l'ajout de delegate.
var maClasse = new MaClasse(); // il n'est pas possible d'assigner directement un delegate à un event maClasse.MonEvent = null; // on peut juste ajouter un delegate à l'event maClasse.MonEvent += (_sender, _e) => { /* ... */ }; |