1

一直在对 ObservableCollection 实现进行一些研究,我发现了一些我无法理解的代码。这是.Net Reflector反编译的代码片段:

[NonSerialized]
private NotifyCollectionChangedEventHandler CollectionChanged;
[NonSerialized]
private PropertyChangedEventHandler PropertyChanged;

event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
  add
  {
    this.PropertyChanged += value;
  }
  remove
  {
    this.PropertyChanged -= value;
  }
}

public virtual event NotifyCollectionChangedEventHandler CollectionChanged
{
  add
  {
    NotifyCollectionChangedEventHandler changedEventHandler = this.CollectionChanged;
    NotifyCollectionChangedEventHandler comparand;
    do
    {
      comparand = changedEventHandler;
      changedEventHandler = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref this.CollectionChanged, comparand + value, comparand);
    }
    while (changedEventHandler != comparand);
  }
  remove
  {
    NotifyCollectionChangedEventHandler changedEventHandler = this.CollectionChanged;
    NotifyCollectionChangedEventHandler comparand;
    do
    {
      comparand = changedEventHandler;
      changedEventHandler = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref this.CollectionChanged, comparand - value, comparand);
    }
    while (changedEventHandler != comparand);
  }
}

protected virtual event PropertyChangedEventHandler PropertyChanged
{
  add
  {
    PropertyChangedEventHandler changedEventHandler = this.PropertyChanged;
    PropertyChangedEventHandler comparand;
    do
    {
      comparand = changedEventHandler;
      changedEventHandler = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.PropertyChanged, comparand + value, comparand);
    }
    while (changedEventHandler != comparand);
  }
  remove
  {
    PropertyChangedEventHandler changedEventHandler = this.PropertyChanged;
    PropertyChangedEventHandler comparand;
    do
    {
      comparand = changedEventHandler;
      changedEventHandler = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.PropertyChanged, comparand - value, comparand);
    }
    while (changedEventHandler != comparand);
  }
}

我无法理解的是为什么 PropertyChanged 有两个(公共和私有)实现,但 CollectonChanged 只有一个(受保护)?在 do-while 循环中委托算术的目的是什么?为什么不像 PropertyChanged 的​​私有实现那样只是“this.Property += value”?

4

1 回答 1

1

避免使用反编译器查看框架代码,而是使用可以从参考源获得的实际源代码。此类的源代码位于 Source.NET 4.5\4.6.0.0\net\fx\src\CompMod\System\Collections\ObjectModel\ObservableCollection.cs 目录中。然后,您将看到 CollectionChanged 事件的真正样子:

    //------------------------------------------------------
    /// <summary>
    /// Occurs when the collection changes, either by adding or removing an item.
    /// </summary>
    /// <remarks>
    /// see <seealso cref="INotifyCollectionChanged"/>
    /// </remarks>
    [field:NonSerializedAttribute()]
    public virtual event NotifyCollectionChangedEventHandler CollectionChanged;

就是这样,没有更多的代码。

反编译器不够智能,无法识别 C# 编译器为实现事件而生成的自动生成代码,因此不知道如何将其折叠回事件的真实C# 代码。造成这种缺陷的至少部分原因是在 .NET 4.0 中发生了变化。do-while 循环是新的,用于确保事件订阅是线程安全的。旧方法使用 [MethodImpl(MethodImplOptions.Synchronized)] 属性使其成为线程安全的。其中有一个缺陷,它锁定了this,这种做法可能会导致无意的死锁。

是的,有两个 PropertyChanged 事件。一个是 INotifyPropertyChanged 的​​显式实现,它只使用另一个。这样做是为了确保事件不是公开的,正如您继承接口时通常会发生的那样,它被重新声明为protected

于 2013-10-04T12:46:08.273 回答