score:3

Accepted answer

This won't work because there is no implicit conversion between List<doohickey> and IEnumerable<NotifyPropertyChanging>. You need to call:

Update(doohickeys.Cast<INotifyPropertyChanging>());

The reason behind this is type safety. In C#4, co-/contravariance was added to the language, which generally helps making these type of conversions valid. There are some limitations though, since the type involved needs to be declared co-/contravariant, and it only applies to interfaces and delegates.

The reason why you can't implicitly convert List<T> to List<TBase> is, that it would make this code valid:

List<T> values = new List<T>();
// add some values...
List<TBase> bases = values;
bases.Add(new TBase());  // Woops. We broke type safety by adding a TBase to a list of T's

Now, if you tried to do this when values was of type IEnumerable<T>, it would be valid in C#4. This is because you can only get values out of IEnumerable<T>, so we don't need to worry about lesser types being added. Therefore IEnumerable<T> is covariant, and is declared as:

IEnumerable<out T>

Where out means "covariant". (The keywords is actually the best way to remember which way values may go in a variant type.

Co-/contravariance is a rather large subject, but this article does a good job of explaining the most important parts. And if you want to learn more, Eric Lippert has an 11-part blog post series about the feature. Eric is one of the language designers.


Related Articles