views:

19

answers:

2

Hello,

I work on a project in Silverlight and I wanted to know how does the ObservableCollection work. I was quite surprised to see this in Reflector:

public class ObservableCollection<T> :
             Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
    // Fields
    private bool _busy;

    // Events
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    protected event PropertyChangedEventHandler PropertyChanged;

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
...

How can it have 2 events with the same name and type? Whats going on? Is this a bug in Reflector?

A: 

It's called an explicit declaration. It's the same way that a generic collection can have two GetEnumerator() methods. One is declared as public; the other is declared as explicit.

Jarrett Meyer
+2  A: 

No, this is explicit interface implementation. This line:

protected event PropertyChangedEventHandler PropertyChanged;

can't implement the INotifyPropertyChanged contract, because it's not public. Other classes can't refer to it, so the ObservableCollection doesn't look to its clients like it implements the interface it says it does. E.g.

ObservableCollection<string> coll;
// ObservableCollection implements INotifyPropertyChanged, so I should be able to...
coll.PropertyChanged += ...
// ... but this wouldn't compile because PropertyChanged is protected

To get around this, ObservableCollection adds another implementation of PropertyChanged, which is "scoped" to the INotifyPropertyChanged interface. That is, it's available only if a client accesses the ObservableCollection via a reference of type INotifyPropertyChanged, in which case it's effectively public. So now clients who want to use the fact that ObservableCollection implements INotifyPropertyChanged will be happy, because the event they're looking for is there:

INotifyPropertyChanged notifier = coll;
notifier.PropertyChanged += ...  // compiles (using explicit implementation)

But the added PropertyChanged doesn't conflict with the protected member with the same name because it's scoped with that INotifyPropertyChanged. prefix.

itowlson