2013-03-18 59 views
1

我對C#的理解是,除非該方法被標記爲虛擬,否則子類不能覆蓋父項的方法實現。如果一個子類聲明一個父方法名稱相同的方法,其而不是標記爲虛擬,它只是隱藏該方法,以便如果從父類型的引用調用該方法,它將調用父方法,如果它從子類類型的引用中調用,它將調用子類方法。但是,我在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<String>,而不是當它被引用爲Collection<String>時。但是有兩件事被解僱了。結果是:

Collection Change! 
Collection Change! 

任何人都可以解釋這裏發生了什麼?

回答

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); 
    } 
} 
0

的ObservableCollection < T>從收集< T>和通知事件將被處理,其中它被分配其在的ObservableCollection類中定義的處理程序導出,添加方法收集的調用插入方法,該方法是虛擬並在ObservableCollection類中重寫,並在重寫的方法中調用事件處理程序。

+0

好的,這是有道理的。謝謝! – NFlick 2013-03-18 06:12:43