2012-04-03 91 views
5

在实现其最基本的形式INotifyPropertyChanged接口,大多数人似乎实现它这样的:INotifyProperyChanged - 为什么要额外分配?

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

我的问题是:为什么的var propertyChanged = PropertyChanged;额外分配?这只是一个偏好问题,还是有充分的理由?当然以下是有效的?

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 – 2012-04-03 06:59:53

回答

4

分配给一个临时变量消除了空校验和上次事件订阅,退订之间的竞争条件的机会。请参阅.NET事件指南here

剪断:

// 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

好的,所以这是一个线程安全的问题。但是在MVVM应用程序中,所有这些调用都是由主Dispatcher完成的,所以这不是一个真正的问题,是吗? – Per 2012-04-03 07:11:45

+0

不一定。是的,视图将添加/删除订阅者在主GUI线程上的绑定。但是您可以在非GUI线程上创建其他模型,该模型订阅ViewModel属性上的更改。当然,这可能不是一个很好的设计实践,也许这些模型应该通过事件聚合器接收通知。 – 2012-05-31 00:31:37

1

这对多线程环境中,在执行之前其它的线程的情况下设置为null

通过使用本地变量,这是被阻止的,并且分配的委托仍然会被调用。

1

在多线程应用程序中,可能(在第二个示例中)检查以查看PropertyChanged != null(让我们假设它不为null)并实际调用委托之后,您的线程被另一个正在注销的last来自委托的事件侦听器。然后,当原始线程恢复并呼叫PropertyChanged(this, new PropertyChangedEventArgs(propertyName));它现在将为空,并且将抛出NullReferenceException

相关问题