Why can I discard the invariance of IList <T>?
I am currently preparing a presentation of new common variance features in C # for my colleagues. In short, I wrote the following lines:
IList<Form> formsList = new List<Form> { new Form(), new Form() };
IList<Control> controlsList = formsList;
Yes, this, of course, is impossible, since IList (Of T) is invariant (at least in my mind). 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>. there is an explicit conversion (do you miss the role?)
Hm, does this mean that I can force an explicit conversion? I just tried:
IList<Form> formsList = new List<Form> { new Form(), new Form() };
IList<Control> controlsList = (IList<Control>)formsList;
And ... it compiles! Does this mean that I can drop immutability? - At least the compiler is fine with this, but I just turned the former compile-time error into a runtime 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]'.
(): IList<T> ( )? ( IList(Of Form) IList(Of Control) )? #, ?
, IList<Control>, IList<Form>, , ( : , . , , ).
:
public class EvilList : IList<Form>, IList<Control> { ... }
, CLR. , , .
, :
castclass [mscorlib]System.Collections.Generic.IList`1<class [System.Windows.Forms]System.Windows.Forms.Control>
MSDN:
castclass ( O) . , . (, ) , InvalidCastException. , castclass .
InvalidCastException , obj .
, , TextBlock . TextBlock controlList, formList.
IList<Form> formsList = new List<Form> { new Form(), new Form() };
IList<Control> controlsList = (IList<Control>)formsList;
controlsList.Add(New TextBlock); // Should throw at runtime.
. controlList IEnumerable, IList ( .Net 4.0), IEnumerable (IEnumerable). , .Add( ) .