que por lo general evitar este declarando nuestros eventos como éste:
public event EventHandler<FooEventArgs> Foo = delegate { };
esto tiene dos ventajas. El primero es que no tenemos cheque para null. La segunda es que se evita el problema de la sección crítica que es omnipresente en el típico caso de fuego:
// 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);
}
Pero con la inicialización automática de Foo a un delegado de vacío, nunca hay ninguna comprobación necesaria y el código es automáticamente thread- segura y fácil de leer para el arranque:
protected virtual void OnFoo(FooEventArgs e)
{
Foo(this, e); // always good
}
con perdón de Pat Morita en el Karate Kid, "la mejor manera de evitar nula no se tiene."
En cuanto al por qué, C# no te mima tanto como VB. Aunque la palabra clave de evento oculta la mayoría de los detalles de implementación de multicast delegates, le da un control más fino que VB.
Francamente, lo veo como * muy * molestia menor. Prefiero una excepción sobre los errores silenciosos. – ChaosPandion
Aunque, a veces, cuando veo * "frameworks" * lanzando muchos 'NullReferenceExceptions' mi resolución se debilita. – ChaosPandion
abundancias inconstancias. Todavía no puedo llamar 'Nullable .HasValue' sin pensar" ¡no puedes acceder a una propiedad con un valor que podría ser nulo! " –