di solito ovviare a questo dichiarando nostri eventi come questo:
public event EventHandler<FooEventArgs> Foo = delegate { };
questo ha due vantaggi. Il primo è che non abbiamo il controllo per null. Il secondo è che si evita il problema sezione critica che è onnipresente in tipico cottura evento:
// old, busted code that happens to work most of the time since
// a lot of code never unsubscribes from events
protected virtual void OnFoo(FooEventArgs e)
{
// two threads, first checks for null and succeeds and enters
if (Foo != null) {
// second thread removes event handler now, leaving Foo = null
// first thread resumes and crashes.
Foo(this, e);
}
}
// proper thread-safe code
protected virtual void OnFoo(FooEventArgs e)
{
EventHandler<FooEventArgs> handler = Foo;
if (handler != null)
handler(this, e);
}
Ma con l'inizializzazione automatica Foo un delegato vuoto, non c'è mai verifiche necessarie e il codice viene automaticamente filettatura sicuro e più facile da leggere al boot: "il modo migliore per evitare di nulla non è avere uno"
protected virtual void OnFoo(FooEventArgs e)
{
Foo(this, e); // always good
}
Con tante scuse a Pat Morita nel Karate Kid,
Per quanto riguarda il perché, C# non ti coccola tanto quanto VB. Sebbene la parola chiave evento nasconda la maggior parte dei dettagli di implementazione di multicast delegates, ti dà un controllo migliore di VB.
Abbastanza francamente lo vedo come un disturbo * molto * minore. Preferisco di gran lunga un'eccezione rispetto agli errori silenziosi. – ChaosPandion
Sebbene, a volte quando vedo * "frameworks" * lanciando un sacco di 'NullReferenceExceptions' la mia risoluzione si indebolisce. – ChaosPandion
Le incoerenze abbondano. Non riesco ancora a chiamare 'Nullable .HasValue' senza pensare" non puoi accedere a una proprietà su un valore che potrebbe essere nullo! " –