The reason why the implicit cast from IList<string>
to IList<object>
won't compile is, as you seem to know, that the IList<T>
interface is not covariant in T
. If, with .NET 4.5, you used IReadOnlyList<out T>
instead, it would work.
The reason why the explicit cast
listObject = (IList<object>)listString;
will compile, is not that IList<string>
and IList<object>
are related in any way. Neither type is assignable to the other. The reason is that the runtime type of your variable (listString
) might be a class (or struct) which implemented both interfaces! Suppose I made this class:
class CrazyList : IList<string>, IList<object> // not very smart
{
// a lot of explicit interface implementations here
}
Then if some IList<string>
happened to be a CrazyList
at runtime, the explicit cast would succeed. When you write an explicit cast, you're telling the compiler "I know the type is going to be convertible to this type I'm casting into". Since the compiler can't prove you're wrong, of course it believes you.