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 = ...       
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
    {      
        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.
 
No comments:
Post a Comment