difference between List<object> and List<MyClass>

  • Thread starter Thread starter Stephan Steiner
  • Start date Start date
S

Stephan Steiner

Hi

I seem to have a bit of trouble understanding one bit of how generics work:

In C#, every class automatically derives from object, and inherits a bunch
of properties (i.e. ToString()). Thus,

(MyClass is object) should always evaluate as true.

However, if I have a method with the following signature:

private void myMethod(List<object> input)

And I try to call it

myMethod(new List<MyClass>())

the compiler complains that it cannot convert from
System.Collections.Generic.List<MyNamespace.MyClass> to
System.Collections.Generic.List<object>. And if I try to cast List<MyClass>
to List<object> that doesn't work either.

Likewise

List<object> myObjs = new List<object>();
myObjs.AddRange(new List<MyClass>());

fails with the same error. However, if I I fill up myObjs as follows:

List<object> myObjs = new List<object>();
List<MyClass> myClasses = new List<MyClass>();
foreach (MyClass c in myClasses)
{
myObjs.Add((object)c);
}

then it works. Even if I leave away the cast to object in the line
myObjs.Add(..) it works (as is to be expected since MyClass is an object.

Since ever class derives from object, why do the the first two examples not
work? Does class inheritance not translate into generics inheritance?

Regards
Stephan
 
Since ever class derives from object, why do the the first two examples not
work? Does class inheritance not translate into generics inheritance?

Generics aren't covariant by type parameter - so as you say, List<Foo>
doesn't derive from List<Bar> just because Foo derives from Bar.

In the general case, this is a good thing which improves type safety.
Suppose it worked as you expected it to. In that case, this code would
compile, but have to fail at run time:

List<string> strings = new List<string>();
List<object> objects = strings;
objects.Add(new object());

Now, in the case of APIs which only ever *return* values of their type
parameter, it would be okay - and contravariance would be acceptable
for APIs which only ever receive values of their type parameter as
method parameters. That's available in the CLR for interfaces, but C#
doesn't expose it.

Hope that helps. Here's a lot more on it:

http://blogs.msdn.com/rmbyers/archive/2005/02/16/375079.aspx
http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx

Jon
 
(orhttp://tinyurl.com/3awpp7)

;-p

Indeed. Note how my example was exactly the same too - though retyped!

I really must get round to writing an article about it some time -
it's probably the most frequently asked question about generics.

Jon
 

Not it hasn't.. I'm sorry about the repost.. for some wicked reason,
neither the original message nor this one ever showed up in OE (ever
other message I post does show up) - so I figured for some reason they
had been discarded.. only when I used google groups to search for my
messages did I find both - plus all the answers.

Thanks to Jon for the explanation and links on the topic - they're
very helpful.

Regards
Stephan
 
Back
Top