【问题标题】:Method overriding/hiding behavior in C#C# 中的方法覆盖/隐藏行为
【发布时间】:2013-03-18 06:01:45
【问题描述】:

我对 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 类不能覆盖Collection 类的Add 方法,我希望只触发一个集合更改事件当对象被引用为ObservableCollection&lt;String&gt; 时,而不是当它被引用为Collection&lt;String&gt; 时。但是触发了两个事件。结果是:

Collection Change!
Collection Change!

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

【问题讨论】:

    标签: c# inheritance polymorphism overriding


    【解决方案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);
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 好的,有道理。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      • 2014-08-13
      相关资源
      最近更新 更多