1

我对 C# 的理解是,子类不能覆盖父类的方法实现,除非该方法被标记为虚拟。如果子类声明了一个与父方法同名但没有标记为虚拟的方法,它只是隐藏了该方法,因此如果从父类型的引用调用该方法,它将调用父方法,如果它是从子类类型的引用中调用它将调用子类方法。但是,我在 C# 库中发现一种情况似乎破坏了这种行为。

Collection<T>声明一个public void Add(T item)方法。此方法不是虚拟的,因此子类中的实现不应覆盖其行为。然而,下面的测试产生了矛盾的结果。

public void Test()
{
    ObservableCollection<String> strings1 = new ObservableCollection<String>();
    strings1.CollectionChanged += OnCollectionChanged;
    strings1.Add("One String");
    Collection<String> strings2 = strings1;
    strings2.Add("Another String");
}

public void OnCollectionChanged(Object source, 
    NotifyCollectionChangedEventArgs e)
{
    Console.WriteLine("Collection Change!");
}

由于该NotifyCollectionChanged行为未在Collection类中实现,并且ObservableCollection该类不能覆盖该类的Add方法,因此Collection我希望仅当对象被引用为 a 时才会触发集合更改事件ObservableCollection<String>,而不是当它被引用为 a 时Collection<String>。但是有两个事件被触发。结果是:

Collection Change!
Collection Change!

谁能解释这里发生了什么?

4

2 回答 2

1

ObservableCollection 没有自己的 Add 方法。相反,它依赖于 Collection 类 Add,即:

public class Collection<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
   {
     public void Add(T item)
     {
          if (this.items.IsReadOnly)
            ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
          this.InsertItem(this.items.Count, item);
     }

     protected virtual void InsertItem(int index, T item)
     {
          this.items.Insert(index, item);
     }     
  }

而InsertItem 是一个在ObservableCollection 中被覆盖的虚方法。

  public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
  {
    protected override void InsertItem(int index, T item)
    {
      this.CheckReentrancy();
      base.InsertItem(index, item);
      this.OnPropertyChanged("Count");
      this.OnPropertyChanged("Item[]");
      this.OnCollectionChanged(NotifyCollectionChangedAction.Add, (object) item, index);
    }
}
于 2013-03-18T06:06:25.560 回答
0

ObservableCollection<T> 是从 Collection<T> 派生的,通知事件将在分配给 ObservableCollection 类中定义的处理程序的地方进行处理,Collection 的 Add 方法调用 Insert 方法,该方法是虚拟的并在 ObservableCollection 类和被覆盖的方法调用事件处理程序。

于 2013-03-18T06:10:52.920 回答