2010-05-07 8 views
5

Je crée des événements personnalisés pour C# et parfois cela ne fonctionne pas.Question sur les événements personnalisés

Voilà comment je fais l'événement se produire:

private bool isDoorOpen; 
    public bool IsDoorOpen { 
     get { return isDoorOpen;} 
     private set { isDoorOpen = value; DoorsChangeState(this, null);} 
    } 

Et ce sont les déclarations d'événement:

//events   
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e); 
    public event ChangedEventHandler PositionChanged; 
    public event ChangedEventHandler DirectionChanged; 
    public event ChangedEventHandler BreaksChangeState; 
    public event ChangedEventHandler DoorsChangeState; 

Cela fonctionne aussi longtemps que il y a des méthodes attachées aux événements, mais si ce n'est pas le cas, il lève une exception de référence nulle. Qu'est-ce que je fais mal?

Répondre

10

La méthode recommandée pour appeler un événement est

var handler = this.DoorsChangeState; 
if (handler != null) 
    handler(this, null); 

La raison de la copie du gestionnaire est localement Incase les changements de gestionnaire d'événements sur un autre thread alors que vous vérifiez pour null.

EDIT: Trouvé l'article parlant des conditions de course. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

+0

+1 n'a pas réalisé la questions de sécurité thread là et le fait que les événements sont immuables. Merci pour le lien. –

0

Si un événement n'est pas abonné lorsqu'il se déclenche, une exception NullReferenceException sera levée. C'est un comportement correct, pas quelque chose que vous avez mal fait.

Vous devriez vérifier:

if(DoorsChangeState != null) 
{ 
    DoorsChangeState(this, null); // Only fire if subscribed to 
} 
0

Avant d'appeler un événement que vous devez vérifier si l'événement est nul:

if (DoorsChangeState != null) 
    DoorsChangeState(this, null); 

Lorsque DoorsChangeState est nul cela signifie qu'il n'y a pas d'auditeurs sur cet événement.

0

Vous devez vérifier si l'événement a été abonné. J'utilise ce formulaire standard pour lancer tous mes événements.

var temp = EventName; 
if(EventName!= null) 
    temp(this, null); 
4

Je sais que cette question a été discutée (et répondue) plusieurs fois ici sur SO.

également quelque part ici, j'ai obtenu les méthodes d'extension suivantes pour rendre ce modèle plus facile à utiliser:

public static class EventHandlerExtensions 
{ 
    public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, args); 
     } 
    } 

    public static void FireEvent(this EventHandler handler, object sender) 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, EventArgs.Empty); 
     } 
    } 
} 

Donc, dans votre code, vous pouvez dire:

public bool IsDoorOpen 
{ 
    get { return isDoorOpen;} 
    private set 
    { 
     isDoorOpen = value; 
     DoorsChangeState.FireEvent(this); 
    } 
} 
+0

+1 Cela fait une très belle syntaxe! – MPritchard

Questions connexes