2012-02-17 11 views
8

ho lavorato molto con C# di recente, e ho notato che la maggior parte del codice che genera eventi nel codice della mia azienda è fatto in questo modo:C alzando # eventi

EventHandler handler = Initialized; 

if (handler != null) 
{ 
    handler(this, new EventArgs()); 
} 

Io davvero non capisco il motivo per cui, invece, non si può fare proprio farlo:

if (Initialized != null) 
{ 
    Initialized(this, new EventArgs()); 
} 

EDIT:

alcuni spunti di riflessione, ho provato a fare alcuni test su questo:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Test t = new Test(true); 

      while(true) 
      { 
       t.Ev += new EventHandler(t_Ev); 
       t.Ev -= new EventHandler(t_Ev); 
      } 
     } 

     static void t_Ev(object sender, EventArgs e) 
     { 
     } 
    } 

    public class Test 
    { 
     private readonly bool m_safe; 

     public Test(bool safe) 
     { 
      m_safe = safe; 

      Thread t = new Thread(Go); 
      t.Start(); 
     } 

     private void Go() 
     { 
      while (true) 
      { 
       if(m_safe) 
       { 
        RaiseSafe(); 
       } 
       else 
       { 
        RaiseUnsafe(); 
       } 
      } 
     } 

     public event EventHandler Ev; 

     public void RaiseUnsafe() 
     { 
      if(Ev != null) 
      { 
       Ev(this, EventArgs.Empty); 
      } 
     } 

     public void RaiseSafe() 
     { 
      EventHandler del = Ev; 

      if (del != null) 
      { 
       del(this, EventArgs.Empty); 
      } 
     } 
    } 
} 

La versione Unsafe fa arrestare il programma.

+4

Immagino sia necessario chiedere alle persone che hanno scritto il codice originale. –

+2

Vedi http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx –

+0

Ottimo articolo Eric, grazie! – user472875

risposta

9

La prima versione è un tentativo di rendere l'evento thread-safe.

Vedi C# Events and Thread Safety

In realtà, come detto nella discussione, non fa il filo evento di sicurezza. Quindi userei la seconda versione che è più corta invece.

MODIFICA: la sicurezza del thread di eventi è davvero difficile da implementare. Guardare what it might look ... Se non si sta effettivamente occupando di più thread che registrano/annullano la registrazione di eventi, non si dovrebbe perdere tempo con la sicurezza del thread.

+2

heh ... ci stava provando, ma tu mi hai battuto :) –

0

La seconda versione non è thread-safe.

if (Initialized != null) 
{ 
    Initialized(this, new EventArgs()); 
} 

Se le ultime unsubscribes gestore dopo la if (Initialized != null) quindi si finirà con l'eccezione rif nullo.

+3

In realtà nessuna delle due versioni è protetta da thread, a seconda della tua definizione di threadsafe. Certo, puoi evitare il dereferenziamento null, ma la prima versione non evita * potenzialmente invocando un gestore che è stato rimosso su un altro thread. * –