Event
Apparence
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) => { /* ... */ };
|