[Mono-list] Collections of generic objects: IDictionary casting problem
Jonathan Pryor
jonpryor at vt.edu
Sat Dec 9 15:47:38 EST 2006
On Wed, 2006-12-06 at 12:56 +0100, Generic 2006 wrote:
> I have a problem casting collections of generic objects.
Here's the short version: the following is not currently possible with
Generics:
class Base {}
class Derived : Base {}
...
IEnumerable<Derived> d = null;
IEnumerable<Base> b = d; // error
You'd *like* this to work, but it can't, it subverts the type system:
List<string> ls = new List<string> ();
// the following is currently an error; you want this to
// be valid
List<object> lo = ls;
lo.Add ((object) 42); // oops!
Generics are supposed to make code safe, so that you don't get
TypeCastExceptions, but the above can't work -- you can't add an int to
a List<string>.
You're trying to do the same thing, just with more indirection:
> {
> IDictionary<String,Wrapper<InnerType>> types;
> /*
> The following assignment throws a compile-time exception:
>
> error CS0266: Cannot implicitly convert type
> 'System.Collections.Generic.IDictionary<System.String,OuterType1>' to
> 'System.Collections.Generic.IDictionary<System.String,Wrapper<InnerType>>'.
> An explicit conversion exists (are you missing a cast?)
OuterType1 : Wrapper<InnerSubType1>, which is compatible with
Wrapper<InnerType>, but this is *exactly* the scenario I described above
with trying to assign a List<string> to a List<object> (string derives
from object) or assigning a IEnumerable<Derived> to an
IEnumerable<Base>. You can't do that.
Now, there are ways to specify in IL that such conversions are possible
-- iirc these are known as Covariant generic types (or something like
that) -- but C# has no way to express this. (AFAIK, at present only IL
can express this.)
You'll have to modify your code to work around this limitation.
- Jon
More information about the Mono-list
mailing list