关于继承:C#中的方法重写/隐藏行为

Method overriding/hiding behavior in C#

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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类不能重写Collection类的Add方法,所以我希望只有当对象被引用为ObservableCollection时,而不是当它被引用为Collection时,才会触发一个集合更改事件。但有两件事被炒了。结果是:

1
2
Collection Change!
Collection Change!

有人能解释一下这是怎么回事吗?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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中重写的虚拟方法。

1
2
3
4
5
6
7
8
9
10
11
  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);
    }
}

ObservableCollection是从集合中派生的,通知事件将在分配给ObservableCollection类中定义的处理程序的位置进行处理,添加集合方法调用在ObservableCollection类中虚拟并重写的Insert方法,在重写方法中调用事件ha德勒