我对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
方法,因此我我希望只有当对象被引用为ObservableCollection<String>
时才会触发集合更改事件,而不是当它被引用为Collection<String>
时。但是有两件事被解雇了。结果是:
Collection Change!
Collection Change!
有谁能解释这里发生了什么?
答案 0 :(得分:1)
ObservableCollection没有自己的Add方法。相反,它依赖于Collection class 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);
}
}
答案 1 :(得分:0)
ObservableCollection&lt; T&GT;来自Collection&lt; T>并且将处理通知事件,其中为其分配了一个在ObservableCollection类中定义的处理程序,Add Method of Collection调用Insert方法,该方法是ObservableCollection类中的虚拟和重写,并且在重写方法中调用事件处理程序。