Hilo seguro de llamadas de eventos

Una práctica común para evitar condiciones de carrera (en aplicaciones de subprocesos múltiples) al desencadenar eventos es la siguiente:

EventHandler<EventArgs> temp = SomeEvent;
if (temp != null) temp(e);

"Remember that delegates are immutable and this is why this technique works in theory. However, what a lot of developers don't realize is that this code could be optimized by the compiler to remove the local temp variable entirely. If this happens, this version of the code is identical to the first version, so a NullReferenceException is still possible."

El problema (según el libro) es que "este código podría ser optimizado por el compilador para eliminar la variable temporal local por completo. Si esto sucede, esta versión del código es idéntica a la primera versión, por lo que aún es posible una excepción NullReferenceException"

Según CLR a través de C #, aquí hay una mejor manera de forzar al compilador a copiar el puntero del evento.

virtual void OnNewMail(NewMailEventArgs e)
{
    EventHandler<NewMailEventArgs> temp =
                          Interlocked.CompareExchange(ref NewMail, null, null);
    if (temp != null) 
        temp(this, e);
}

Aquí, CompareExchange cambia la referencia de NewMail a null si es nulo y no modifica NewMail si no es nulo. En otras palabras, CompareExchange no cambia el valor en NewMail en absoluto, pero sí devuelve el valor dentro de NewMail de una manera atómica y segura para subprocesos. Richter, Jeffrey (2010-02-12). CLR a través de C # (p. 265). OReilly Media - A. Edición Kindle.

Estoy en .Net 4.0 framework, y no estoy seguro de cómo puede funcionar esto, porque Interlocked.CompareExchange espera una referencia a una ubicación, no una referencia a un evento.

O hay un error en el libro, o lo malinterpreté. ¿Alguien ha implementado este método? ¿O tienes una mejor manera de prevenir las condiciones de carrera aquí?

ACTUALIZAR

Fue mi error, el código bloqueado funciona. Acabo de especificar el lanzamiento incorrecto, pero de acuerdo con Bradley (abajo) no es necesario en .net 2.0 y en Windows.