C# – Adding a collection of a subclass with AddRange

.net-3.5cinheritanceiteration

If I have these two classes:

class A {}
class B : A {}

and I make a List<A> but I want to add a List<B> to it by calling List<A>.AddRange(List<B>) but the compiler refuses:

Argument '1': cannot convert from 'System.Collections.Generic.List<A>'
to 'System.Collections.Generic.IEnumerable<B>

which I completely understand because IEnumerable<B> does not inherit from IEnumerable<A>, its generic type has the inheritance.

My solution is to enumerate through List<B> and individually add items because List<A>.Add(A item) will work with B items:

foreach(B item in listOfBItems)
{
    listOfAItems.Add(item);
}

However, that's rather non-expressive because what I want is just AddRange.

I could use

List<B>.ConvertAll<A>(delegate(B item) {return (A)item;});

but that's unnecessarily convoluted and a misnomer because I'm not converting, I'm casting .

Question: If I were to write my own List-like collection what method would I add to it that would allow me to copy a collection of B's into a collection of A's as a one-liner akin to List<A>.AddRange(List<B>) and retain maximum type-safety. (And by maximum I mean that the argument is both a collection and type inhertance checking.)

Best Answer

Indeed, generic types are not variant right now. In C# 4.0, IEnumerable<B> will be convertible to IEnumerable<A> if B is convertible to A via a reference conversion. For some details on the design of this feature, see:

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx