NFlick
NFlick

Reputation: 11

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. 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. However, I found a situation in the C# library that appears to break this behavior.

The Collection<T> declares a method 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>. But two events are fired. The result is:

Collection Change!
Collection Change!

Can anyone explain what is going on here?

Upvotes: 1

Views: 438

Answers (2)

TalentTuner
TalentTuner

Reputation: 17556

ObservableCollection < T> is derived from the Collection < T > and notification event will be handled where it is assigned a handler which is defined in the ObservableCollection class , Add Method of Collection call the Insert method which is virtual and overridden in ObservableCollection class and in the overridden method its calling the event handler.

Upvotes: 0

alex
alex

Reputation: 12654

ObservableCollection does not have it's own Add method. Instead it relies on Collection class Add, that is:

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.

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

Upvotes: 1

Related Questions