2010-04-08 9 views
11

Auf der MSDN, habe ich gefunden, folgende:Frage in Bezug auf Wert/Referenz Arten von Veranstaltungen

public event EventHandler<MyEventArgs> SampleEvent; 

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

Ist es verweisen?
Wenn ja seine Ich verstehe nicht, Bedeutung wie wenn SampleEvent wurde null, so auch die Temperatur

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

Antwort

12

Dies ist eine Paranoia, was mit einem Gewinde zu tun. Wenn andere Thread die letzte Handler Abo kündigt kurz nach Sie es für null überprüft haben, könnte es werdennull und Sie werden eine Ausnahme verursachen. Da Delegaten unveränderlich sind, verhindert das Erfassen eines Snapshots des Delegaten in einer Variablen dies.

Natürlich tut es das andere Nebeneffekt haben, dass Sie konnte (statt), um das Ereignis gegen ein Objekt Anheben am Ende, dass es bereits unsubscribed denkt ...

Aber Stress - das ist nur ein Problem, wenn mehrere Threads das Objekt abonnieren/abbestellen, was a: selten und b: nicht genau wünschenswert ist.

+0

Eine nette, aber genaue Erklärung: o) –

+3

Beachten Sie, dass Sie * immer * das Ereignis gegen einen Handler auslösen können, der denkt, dass er abgemeldet ist - weil er sich abmelden könnte, nachdem Sie mit der Ausführung des Delegierten begonnen haben. Ich habe den erreicht, der sich abmeldet. –

+0

Also die wichtigste Tatsache hier (um die vernünftige Frage des Fragestellers zu beantworten, dass die Delegierten einen Referenztyp haben) ist, dass "Delegaten unveränderlich" sind, so dass diese Zuweisung "einen ** Schnappschuss ** des Delegierten" enthält. Recht? – AakashM

2

(Von dem, was ich lese C# 4.0 in Essential)

Grundsätzlich von diesem C# -Code:

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

die Compiler CIL-Code (lose) entspricht den folgenden C# -Code generiert:

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

Wenn Sie das Ereignis kopieren, kopieren Sie tatsächlich die private CustomEventHandler customEventHandler. Da der Delegat unveränderlich ist, wird die Kopie nicht beeinflusst, wenn das Original customEventHandler geändert wird. Sie können diesen Code versuchen, um zu sehen, was ich meine:

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

Ein weiteres wichtiges Merkmal über den erzeugten CIL Code zu beachten ist, dass der CIL-Äquivalent des event Schlüsselwort in der CIL bleibt. Mit anderen Worten, ein Ereignis ist etwas, das der CIL-Code explizit erkennt ; es ist nicht nur ein C# -Konstrukt. Durch das Beibehalten eines entsprechenden Schlüsselworts im CIL-Code können alle Sprachen und Editoren spezielle Funktionen bereitstellen, da sie das Ereignis als spezielles -Klassenmitglied erkennen können.

Ich denke, Sie waren vor allem verwirrt, weil Sie dachten, Event ist eine Zuckersyntax für eine Klasse, oder?