2010-05-07 12 views
5

Sto creando eventi personalizzati per C# e talvolta non funziona.Domanda sugli eventi personalizzati

Questo è come mi sto rendendo l'evento accadrà:

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

E queste sono le dichiarazioni di evento:

//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; 

Questo funziona fino a quando ci sono metodi collegati agli eventi, ma se non c'è, lancia un'eccezione di riferimento null. Che cosa sto facendo di sbagliato?

risposta

10

Il modo consigliato di chiamare un evento è

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

La ragione per copiare il gestore a livello locale è Incase i cambiamenti gestore di eventi su un altro thread, mentre si sta controllando per nulla.

MODIFICA: trovato l'articolo che parla delle condizioni di gara. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

+0

+1 non si rendeva conto della problemi di sicurezza di thread lì e il fatto che gli eventi sono immutabili. Grazie per il link. –

0

Se un evento non è sottoscritto al momento in cui viene attivato, verrà generata una eccezione NullReferenceException. Questo è un comportamento corretto, non qualcosa che hai sbagliato.

Si dovrebbe verificare:

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

Prima di invocare un evento è necessario verificare se l'evento è nullo:

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

Quando DoorsChangeState è nulla che significa che non ci sono ascoltatori quell'evento.

0

È necessario verificare se l'evento è stato sottoscritto.

Io uso questo modulo standard per lanciare tutti i miei eventi.

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

So che questa domanda è stata discussa (e ho risposto) più volte qui su SO.

anche da qualche parte qui ho ottenuto i seguenti metodi di estensione per rendere questo modello più facile da usare:

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); 
     } 
    } 
} 

Quindi, nel codice si può dire:

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

+1 Fa una sintassi molto bella! – MPritchard

Problemi correlati