简体   繁体   English

C#中的方法重写/隐藏行为

[英]Method overriding/hiding behavior in C#

My understanding of C# is that a subclass cannot override a parent's implementation of a method unless that method is marked virtual. 我对C#的理解是,除非该方法被标记为虚拟方法,否则子类无法覆盖父方法的实现。 If a subclass declares a method with the same name of a parent method that is not marked virtual, it simply hides that method, so that if the method is called from a reference of the parent type it will call the parent method and if it is called from a reference of the subclass type it will call the subclass method. 如果子类声明的方法与标记为virtual的父方法的名称相同,则只会隐藏该方法,因此,如果从父类型的引用中调用该方法,它将调用该父方法,如果是从子类类型的引用调用后,它将调用子类方法。 However, I found a situation in the C# library that appears to break this behavior. 但是,我在C#库中发现一种情况似乎破坏了此行为。

The Collection<T> declares a method public void Add(T item) . Collection<T>声明一个方法public void Add(T item) This method is not virtual, so implementations in a subclass should not override its behavior. 此方法不是虚拟的,因此子类中的实现不应覆盖其行为。 However, the following test produces a contradictory result. 但是,以下测试产生了矛盾的结果。

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

Since the NotifyCollectionChanged behavior is not implemented in the Collection class, and the ObservableCollection class cannot override the Add method of the Collection class, I would expect a collection change event to be fired only when the object is referenced as a ObservableCollection<String> , not when it is referenced as a Collection<String> . 由于NotifyCollectionChanged行为未在Collection类中实现,并且ObservableCollection类无法覆盖Collection类的Add方法,因此我希望仅当将对象引用为ObservableCollection<String>时才触发集合更改事件。当它被引用为Collection<String> But two events are fired. 但是有两个事件被触发。 The result is: 结果是:

Collection Change!
Collection Change!

Can anyone explain what is going on here? 谁能解释这是怎么回事?

ObservableCollection does not have it's own Add method. ObservableCollection没有它自己的Add方法。 Instead it relies on Collection class Add, that is: 相反,它依赖于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);
     }     
  }

And InsertItem is a virtual method that is overriden in ObservableCollection. 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);
    }
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM