How to assign List <DerivedClass> to IEnumerable <BaseClass> parameter?
I understand that the derived class List <> cannot be directly assigned to List <> of the base class. But how does it allow you to assign the same class List <> from the derived class to the parameter of the IEnumerable <> base class.
public class Base {} public class Derived : Base {} public class Test { // inside some method... List<Derived> someElements; ReadElements(someElements); public void ReadElements(List<Base> elements) // this throws compile error {...} public void ReadElements(IEnumerable<Base> elements) // this one works {...} } I know List is an IEnumerable implementation and supports indexing and modifying elements, but it seems like I don't understand this part? Can someone explain? Thanks.
IList and List do not determine their T as the out , and IEnumerable . List is a class, so it cannot have out , and IList does not define out , because it accepts inputs of type T
Put an easier way to get back T from IEnumerable , but you can put it in T in IList , because of this IEnumerable doesn't matter if you are less specific, but IList does. (This is actually needed, see @ChrisShain's answer for a link to how covariance and contravariance work).
Consider this code, which in itself is completely legal:
public void AddElements(List<Base> elements) { Base item = new Base(); elements.Add(item); } But what happens if you call it this:
List<Derived> elements = new List<Derived>; AddElements(elements); The Base class is not inherited from Derived and therefore cannot be added to the elements list. This is a potential problem, therefore illegal.
On the other hand, IEnumerable<Base> only provides methods for reading the collection, not writing to it, so this contradiction cannot be satisfied.
Since IEnumerable is covariant for a parameter of type T: http://geekswithblogs.net/abhijeetp/archive/2010/01/10/covariance-and-contravariance-in-c-4.0.aspx