正在做一些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”?
答案 0 :(得分:1)
避免使用反编译器查看框架代码,使用可以从Reference Source获取的实际源代码。此类的源位于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)]属性使其成为线程安全的。它有一个缺陷,它会锁定这个,这种做法可能导致无意的死锁。
是的,有两个PropertyChanged事件。一个是INotifyPropertyChanged的显式实现,它只使用另一个。这样做是为了确保事件不是公共的,就像您继承接口时通常会发生的那样,它被重新声明为 protected 。