views:

74

answers:

4

Hi all,

I have

class A
{}

class B : A
{}

I also have a method that expects a List parameter

void AMethod(List<A> parameter)
{}

Why can't I

List<B> bs = new List<B>();
AMethod(bs);

And secondly what is the most elegant way to make this work?

regards

+5  A: 

You could make the method signature generic like this:

void AMethod<T>(List<T> parameter) where T : A
{}

Or, you could wait for .NET 4 where this scenario is supported for IEnumerable<>

Lars Mæhlum
Not for IList<T>...
Alexandra Rusina
Thanks. Corrected :)
Lars Mæhlum
+4  A: 

Have a look at the Covariance and Contravariance FAQ. There are some good explanations and examples (for the upcoming c# 4.0).

tanascius
+1  A: 

The reason is that generics do not support covariance; I have read that this is coming in 4.0

That is why you are not able to pass the list where base type is expected

http://www.boyet.com/Articles/CSharpCovarianceOne.html

Krishna Kumar
+7  A: 

Contrary to other answers, this isn't supported in .NET 4.0. Only interfaces and delegates support generic variance. However, .NET 4.0 would allow you to do this:

void AMethod(IEnumerable<A> parameter) {}
...
List<B> list = new List<B>();
AMethod(list);

In .NET 3.5 you can get much the same thing to work with the aid of Cast:

void AMethod(IEnumerable<A> parameter) {}
...
List<B> list = new List<B>();
AMethod(list.Cast<A>());

Another alternative is to make AMethod generic:

void AMethod<T>(List<T> parameter) where T : A
...
List<B> list = new List<B>();
AMethod(list); // Implicitly AMethod<B>(list);

That may or may not do what you need - it depends on what you do within AMethod. If you need to add new items of type A, you'll have problems - and rightly so. If you only need to get items out of the list, that would be fine.

Jon Skeet