how can I cast List<MyObject> to ICollection<IMyObject>

J

Jimp

Why can't I cast List<MyObject> to ICollection<IMyObject>.

MyObject implements IMyObject, and of course, List implements
ICollection.

Thanks
 
J

Jon Skeet [C# MVP]

Jimp said:
Why can't I cast List<MyObject> to ICollection<IMyObject>.

MyObject implements IMyObject, and of course, List implements
ICollection.

Because C# generics don't support contravariance/covariance. Even if
they did, you'd need to cast to ICollection<+IMyObject>
(or ICollection<-IMyObject> - I can't remember which way round it is)
rather than ICollection<IMyObject>.

Suppose you *could* cast it. Let's keep things simple and keep it as
casting some IList<string> to IList<object>. It's fine when it comes to
taking elements *out* of the list. It's not so good if you try to add
elements to the list.

Suppose I could do:

IList<string> strings = new List<string>();
IList<object> objects = strings;
// No problem here
object firstObject = objects[0];
// What would this do?
objects.Add (Encoding.UTF8);

It would be trying to add an Encoding to a list of Strings! That would
*have* to fail at runtime, in order to avoid completely violating type
safety. At that stage, you've lost a major point of using generics in
the first place - type safety.

Now, if C# supported covariant/contravariant generics, you *could* do:

IList<string> strings = new List<string>();
IList<+object> objects = strings;

IList<+object> would mean "it's a list of 'something that derives from
object but I don't know what'". (Again, I may have got + and - the
wrong way round, I'm afraid.) That would mean you'd be able to fetch
from the list as object, but not add anything, because you wouldn't
know exactly which type you could add.

Similarly you could do:
IList<object> objects = new List<object>();
IList<-string> strings = objects;

You could then *add* any string to strings, but you couldn't fetch
anything out of it because you wouldn't know what type it was.

I may well have misunderstood all this (in terms of what the CLI
allows) - I've only seen it mentioned in a few places. Anyway, I hope
you can see why C# in its current form, with no added
covariance/contravariance, stops you from doing the cast you want.
 
K

Kevin Spencer

Because List<MyObject> is a specific type, and ICollection<MyObject> is a
specific type, and List<MyObject> does not inherit or impment
ICollection<MyObject>. Generics are compiled to strong data types. The
Generic "classes" are not classes at all, but templates used to create
classes at compile time.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Hard work is a medication for which
there is no placebo.
 
J

Jon Skeet [C# MVP]

Kevin Spencer said:
Because List<MyObject> is a specific type, and ICollection<MyObject> is a
specific type, and List<MyObject> does not inherit or impment
ICollection<MyObject>.

Yes it does - that would be fine. List<MyObject> doesn't implement
ICollection<IMyObject> though - that's the important bit (the type
parameter).

I'm guessing your post was actually a typo, but I thought it would be
worth clarifying quickly :)
 
K

Kevin Spencer

Hi Jon,

Yeah, sorry for muddying the water.
--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Hard work is a medication for which
there is no placebo.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top