If I have two classes:
public class A { }
public class B : A { }
and I create a generic container and a function that takes it:
public void Foo(List<A> lst) { ... }
I get an invalid conversion if I attempt casting a List<B>
to a List<A>
, and instead have to pass it like so:
var derivedList = new List<B>();
Foo(new List<A>(derivedList));
Is there some way to pass a List<B>
to this function without the overhead of allocating a brand new list, or does C# not support converting from a generic container of a derived type to its base type?
A List<B>
simply isn't a List<A>
- after all, you can add a plain A
to a List<A>
, but not to a List<B>
.
If you're using C# 4 and .NET 4 and your Foo method only really needs to iterate over the list, then change the method to:
public void Foo(IEnumerable<A> lst) { ... }
In .NET 4, IEnumerable<T>
is covariant in T
, which allows a conversion from IEnumerable<B>
(including a List<B>
) to IEnumerable<A>
. This is safe because values only ever flow "out" of IEnumerable<A>
.
For a much more detailed look at this, you can watch the video of the session I gave at NDC 2010 as part of the torrent of NDC 2010 videos.
This is not possible. C# doesn't support co / contra variance on concrete types such as List<T>
. It does support it on interfaces though so if you switch Foo
to the following signature you can avoid an allocation
public void Foo(IEnumerable<A> enumerable) { ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With