Have you ever thought about why the following code works? Or are you astounded why I ask this question?
class Base{}
class Derived : Base{}
void Foo(Base[] b)
{
foreach(Base b in b)
Console.WriteLine(b);
}
Foo(new Derived[]{new Derived(), new Derived()});
Arrays are covariant in C#. This means that you can assign an array of derived types to an array of base types as shown above. Having a strong C++ background, I always wondered why this is possible, because typeof(object[])!= typeof(A[]) is definitely true. And what even makes me wonder more is how often I use the covariance of arrays today!
I noticed that I unintentionally adopted it, when I first tried out .NET Generics about a year
ago and asked myself whether I can pass an IEnumerable<Derived> as an IEnumerable<Base>. Well, I couldn't and was a little bit disappointed. Of course I understand that generics are not covariant and shouldn't be, but still it was annoying to copy the content of one collection to another:
IEnumerable<Base> derived = ...
ICollection<Base> copy = new List<Base>();
foreach(Derived d in derived)
copy.Add(d); So I decided to provide an adapter implementation to avoid the copying. The new C# 2.0 iterator feature made this task very easy. Basically it generates the IEnumerable<T> implementation for you and eliminates the need for the for copying the collection:
public static class Adapt
{
public static IEnumerable<Base>
Covariant(IEnumerable<Derived> derived) where Derived : Base
{
foreach (Derived b in derived)
yield return b;
}
}
This covariant adapter and some more for adapting non generic collections of the System.Collections namespace to their generic counterpart and vice versa are available through the NSTL project, a port and adaption of the C++ STL for .NET.