Currently I'm preparing a presentation of the new generic variance features in C# for my colleagues. To cut the story short I wrote following lines:
IList<Form> formsList = new List<Form> { new Form(), new Form() };
IList<Control> controlsList = formsList;
Yes, this is of course not possible, as IList(Of T) is invariant (at least my thought). The compiler tells me that:
Cannot implicitly convert type
System.Collections.Generic.IList<System.Windows.Forms.Form>
toSystem.Collections.Generic.IList<System.Windows.Forms.Control>
. An explicit conversion exists (are you missing a cast?)
Hm, does this mean I can force an explicit conversion? I just tried it:
IList<Form> formsList = new List<Form> { new Form(), new Form() };
IList<Control> controlsList = (IList<Control>)formsList;
And… it compiles! Does it mean I can cast the invariance away? - At least the compiler is ok with that, but I just turned the former compile time error to a run time error:
Unable to cast object of type 'System.Collections.Generic.List`1[System.Windows.Forms.Form]' to type 'System.Collections.Generic.IList`1[System.Windows.Forms.Control]'.
My question(s): Why can I cast the invariance of IList<T>
(or any other invariant interface as to my experiments) away? Do I really cast the invariance away, or what kind of conversion happens here (as IList(Of Form)
and IList(Of Control)
are completely unrelated)? Is this a dark corner of C# I didn't know?