2

I'mm building a WPF app with MVVM and am using ObservableCollection. While working on my ViewModel, I decided to inspect the type definition of the ObservableCollection and I saw something that I thought was odd:

// class definition for ObservableCollection
ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
// derives from Collection<T>
... 
// class definition for Collection<T>
Collection<T> : IList<T>, ICollection<T>, IEnumerable<T> ... (as well as non-generics)

Now, here's the question:

If ICollection<T> implements IEnumerable<T> 
AND 
IList<T> implements ICollection<T> AS WELL AS IEnumerable<T>
...
...
Why does Collection<T> implement ALL THREE?

Is this really how its implemented or is this VS2010 playing tricks on me?

Glenn Ferrie
  • 10,290
  • 3
  • 42
  • 73
  • My interpretation is that it implements the interface directly. – paparazzo Nov 10 '12 at 20:29
  • @Blam - Can you clarify your comment? Using "it" and "the interface" is not constructive when the question discusses multiple classes and interfaces – Glenn Ferrie Nov 10 '12 at 20:34
  • If it is not constructive then just ignore it. It would be the subject of the question. Interface would be interface. Implement directly would be implement directly. – paparazzo Nov 10 '12 at 20:52

2 Answers2

6

If a class, say Collection<T> implements IList<T>, and you would go to the definition in Visual Studio, it will show you all interfaces that Collection<T> implements. If Collection<T> implements IList<T>, it will also implement ICollection<T> and IEnumerable because

IList<T> : ICollection<T>

and

ICollection<T> : IEnumerable<T>

etc.

In otherwords, if I write

interface IFoo : IBar, IBaz {}
interface IBar {}
interface IBaz {}

class Foobar : IFoo {}

Then Visual Studio will give me:

Foobar : IFoo, IBar, IBaz {...} (from metadata).

If I implement IFoo, I must also implement IBar because IFoo extends IBar, thus it makes sense to show that Foobar also implement IBar and IBaz (otherwise I'd only see IFoo, and would have to navigate to IFoo to see IBar etc.)

Marcus
  • 5,987
  • 3
  • 27
  • 40
  • Good example. In short, the relationship *implements* is transitive. – Eric Mickelsen Nov 10 '12 at 21:21
  • 1
    Good answer. I would add that explicitly specifying the base interfaces makes no difference to the compiler - once you've specified that something is an `IList` (and therefore an `ICollection`) specifying `ICollection` *again* is valid although redundant. Also, [Eric Lippert has a post on the subject](http://blogs.msdn.com/b/ericlippert/archive/2011/04/04/so-many-interfaces.aspx). – anton.burger Nov 10 '12 at 21:41
  • Sure, this is what I thought (+1). I found another scenario that somewhat contrasts with this explanation. System.Data.DataSet implements MarshalByValueComponent with itself implements IDisposable.. ... but I don't see the IDisposable in the DataSet class definition. What gives? – Glenn Ferrie Nov 10 '12 at 22:56
  • I'd guess it's simply a design decision made when implementing "Go To Definition", along with the distinction between displaying a base class vs showing implemented interfaces - for interfaces implemented *by the class being viewed*, it was deemed useful to show the entire interface list. Interfaces implemented by its *base* class are perhaps less directly relevant in most cases (though it's always good to know when something is disposable). Whether explicitly shown or not, `DataSet` of course implements `IDisposable` through its base class. – anton.burger Nov 10 '12 at 23:56
  • It'd be nice if the tooling evolved to show the ACTUAL definition of types where that information is made public. Thanks for the input. I'll accept this answer. – Glenn Ferrie Nov 11 '12 at 03:35
-1

Actually not only Visual Studio, but other tools (like Reflector) also will show all interfaces, which are implemented by type. I think this functionality is implemented via Type.GetInterfaces:

Type type = typeof(MyClass);
Type[] interfaces = type.GetInterfaces();

This method gets all the interfaces implemented or inherited by the current Type. Implemented interfaces are those, which are declared as a part of definition of the Type:

public class MyClass : IList<T>

But interfaces can inherit other interfaces. So interfaces, which are inherited by implemented interfaces, are inherited interfaces:

 public interface IList<T> : ICollection<T>

 public interface ICollection<T> : IEnumerable<T>

 public interface IEnumerable<T> : IEnumerable

So, here we have three inherited interfaces and one implemented. All are considered as type interfaces.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459