2012-04-03 13 views
5

Al implementar la interfaz INotifyPropertyChanged en su forma más básica, la mayoría de la gente parece implementarlo como esto ::INotifyProperyChanged: ¿por qué la asignación extra?

public virtual void OnPropertyChanged(string propertyName) 
{ 
    var propertyChanged = PropertyChanged; 
    if (propertyChanged != null) 
    { 
     propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

Mi pregunta es: ¿Por qué la asignación adicional de var propertyChanged = PropertyChanged;? ¿Es solo cuestión de preferencia o hay una buena razón para ello? Sin duda, lo siguiente es tan válido?

public virtual void OnPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
+1

http://stackoverflow.com/questions/786383/c-sharp-events-and-thread-safety –

Respuesta

4

La asignación a una variable temporal elimina la posibilidad de una condición de carrera entre el cheque nulo y la última suscriptor de eventos, darse de baja. Consulte las Pautas de eventos de .NET here.

Snip:

// Make a temporary copy of the event to avoid possibility of 
    // a race condition if the last subscriber unsubscribes 
    // immediately after the null check and before the event is raised. 
    EventHandler<CustomEventArgs> handler = RaiseCustomEvent; 
+0

Ok, entonces es una cuestión de seguridad. Pero en una aplicación MVVM, todas estas llamadas se realizan desde el distribuidor principal, por lo que no es realmente un problema, ¿o sí? – Per

+0

No necesariamente. Sí, las vistas agregarán/eliminarán suscriptores para sus enlaces en el hilo principal de la GUI. Pero podría tener otros Modelos, creados en un hilo que no sea de GUI, que se suscriban a los cambios en la propiedad de un ViewModel. Por supuesto, esto podría no ser una gran práctica de diseño y tal vez esos Modelos deberían recibir notificaciones a través de un Agregador de eventos. –

1

Es para entornos multiproceso, donde algún otro flujo pueda crear el evento para null antes de ser ejecutado.

Al usar la variable local, esto se evita y los delegados asignados seguirán siendo llamados.

1

En una aplicación multiproceso, es posible que (en su segundo ejemplo) entre comprobación para ver si PropertyChanged != null (supongamos que no es nulo) y llame realmente al delegado, el hilo sea anulado por otro que esté anulando el registro el último detector de eventos del delegado. Luego, cuando el hilo original se reanude y llame al PropertyChanged(this, new PropertyChangedEventArgs(propertyName));, ahora será nulo y se lanzará un NullReferenceException.

Cuestiones relacionadas