【问题标题】:INotifyProperyChanged - why the extra assignment?INotifyProperyChanged - 为什么要额外分配?
【发布时间】:2012-04-03 06:53:41
【问题描述】:

当以最基本的形式实现INotifyPropertyChanged接口时,大多数人似乎是这样实现的::

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));
    }
}

【问题讨论】:

标签: c# .net inotifypropertychanged


【解决方案1】:

对临时变量的赋值消除了空检查和最后一个事件订阅者(取消订阅)之间出现竞争条件的可能性。请参阅 .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; 

【讨论】:

  • 好的,这是线程安全的问题。但是在 MVVM 应用程序中,所有这些调用都是从主 Dispatcher 发出的,所以这不是问题,不是吗?
  • 不一定。是的,视图将为其在主 GUI 线程上的绑定添加/删除订阅者。但是您可以在非 GUI 线程上创建其他模型,以订阅 ViewModel 属性的更改。当然,这可能不是一个很好的设计实践,也许这些模型应该通过事件聚合器接收通知。
【解决方案2】:

它适用于多线程环境,其中一些其他线程可能会在事件执行之前将事件设置为null

通过使用局部变量可以防止这种情况发生,分配的委托仍然会被调用。

【讨论】:

    【解决方案3】:

    在多线程应用程序中,有可能(在您的第二个示例中)在检查PropertyChanged != null(假设它不为空)和实际调用委托之间,您的线程可能被另一个线程抢占从委托中取消注册 last 事件监听器。然后当原线程恢复并调用PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 时,它现在将为空,并抛出NullReferenceException

    【讨论】:

      猜你喜欢
      • 2014-03-26
      • 2017-11-28
      • 1970-01-01
      • 2015-08-24
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多