Two basic concepts are presented here: Type Conversions and General Interface Deviations . Where variance is leading.
Case 1: In the definition of List<T> , we do not have variance for a common parameter. So we have no relationship between List<object> and List<string> . They are invariant. Therefore, implicit and explicit type conversion is not possible.
Case 2: List<T> implements IEnumerable<out T> , which is a covariant generic type, so List<string> can be implicitly cast to IEnumerable<object>
DETAILS:
Why is variance not allowed for List<T> but allowed for IEnumerable<T> ?
The point of generics is to provide compilation type security. Since List<T> is writable and if there was no compile time check, we could write the following and have a run-time error:
List<string> stringList = new List<string>(); stringList.Add("some string");
So, unsafe variance for List<T> .
But IEnumerable<out T> is read-only. It does not provide a way to modify the reference instance.
IEnumerable<object> objectList = new List<string>();
Thus, there is a safe dispersion.
source share