2010-04-08 13 views
11

Su MSDN, ho trovato seguente:domanda riguardo al valore di tipo/di riferimento di eventi

public event EventHandler<MyEventArgs> SampleEvent; 

public void DemoEvent(string val) 
{ 
// Copy to a temporary variable to be thread-safe. 
    EventHandler<MyEventArgs> temp = SampleEvent; 

è IT di riferimento?
Se è così non capisco il suo significato come quando SampleEvent diventato nullo, così fa la temperatura

if (temp != null) 
     temp(this, new MyEventArgs(val)); 
} 

risposta

12

Questa è una cosa paranoia a che fare con filettatura. Se un altro thread unsubscribes l'ultimo gestore subito dopo aver controllato per null, potrebbe diventare null e ti causare un'eccezione. Poiché i delegati sono immutabili, catturare un'istantanea del delegato in una variabile impedisce che ciò accada.

Naturalmente, se ha l'altro effetto lato che si potrebbe (invece) finiscono per generare l'evento contro un oggetto che pensa già sottoscritte ...

Ma allo stress - questo è solo un problema quando più thread stanno sottoscrivendo/annullando la sottoscrizione all'oggetto, che è a: raro eb: non esattamente desiderabile.

+0

Una spiegazione carina, ma precisa: o) –

+3

Nota che puoi * sempre * finire sollevando l'evento contro un gestore che ritiene che sia annullato l'iscrizione - perché potrebbe annullare l'iscrizione dopo aver iniziato l'esecuzione del delegato ma prima di te ' ho raggiunto quello che si annulla da solo. –

+0

Quindi il fatto chiave qui (per mirare alla ragionevole domanda del richiedente che i delegati sono di un tipo di riferimento) è che "i delegati sono immutabili", quindi questo incarico "captur [es] a ** snapshot ** del delegato". Destra? – AakashM

2

(Da quello che ho letto in Essential C# 4.0)

In sostanza, da questo codice C#:

public class CustomEventArgs: EventArgs {…} 
public delegate void CustomEventHandler(object sender, CustomEventArgs a); 
public event CustomEventHandler RaiseCustomEvent; 

il compilatore genera il codice CIL (vagamente) equivalente al seguente codice C#:

public delegate void CustomEventHandler(object sender, CustomEventArgs a); 

private CustomEventHandler customEventHandler; // <-- generated by the compiler 

public void add_CustomEventHandler(CustomEventHandler handler) { 
    System.Delegate.Combine(customEventHandler, handler); 
} 

public void remove_CustomEventHandler(CustomEventHandler handler) { 
    System.Delegate.Remove(customEventHandler, handler); 
} 

public event CustomEventHandler customEventHandler { 
    add { add_customEventHandler(value) } 
    remove { remove_customEventHandler(value) } 
} 

Quando si copia l'evento, si copia effettivamente lo private CustomEventHandler customEventHandler. Dal momento che il delegato è immutabile, la copia non verrà modificata quando viene modificato l'originale customEventHandler. Si può provare questo codice per capire cosa intendo:

string s1 = "old"; 
string s2 = s1; 
s1 = "new"; // s2 is still "old" 

Un'altra caratteristica importante da notare sul codice CIL generato è che il CIL equivalente della parola chiave event rimane nel CIL. In altre parole, un evento è qualcosa che il codice CIL riconosce esplicitamente ; non è solo un costrutto C#. Mantenendo una parola chiave equivalente nel codice CIL, tutte le lingue e gli editor sono in grado di fornire funzionalità speciali in quanto possono riconoscere l'evento come membro speciale della classe .

Immagino che tu fossi confuso principalmente perché pensavi che l'evento fosse una sintassi dello zucchero per una lezione, giusto?

Problemi correlati