Question

I am trying to develop a Silverlight 4 application using C# 4.0. I have a case like this:

public class Foo<T> : IEnumerable<T>
{
    ....
}

Elsewhere:

public class MyBaseType : MyInterface
{
    ...
}

And the usage where I am having problems:

Foo<MyBaseType> aBunchOfStuff = new Foo<MyBaseType>();
Foo<MyInterface> moreGeneralStuff = myListOFStuff;

Now I believe this was impossible in C# 3.0 because generic type were "Invariant". However I thought this was possible in C# 4.0 through the new covariance for generics technology?

As I understand it, in C# 4.0 a lot of common interfaces (like IEnumerable) have been modified to support variance. In this case does my Foo class need to anything special in order to become covariant?

And is covariance supported in Silverlight 4 (RC) ?

Was it helpful?

Solution

Covariance is only supported for Interfaces and Delegates:

public interface Foo<out T> { }
public class Bar<T> : Foo<T> { }

interface MyInterface { }
public class MyBase : MyInterface { }

Foo<MyBase> a = new Bar<MyBase>();
Foo<MyInterface> b = a;

Important is the out-Keyword on the Interface Foo.

OTHER TIPS

To indicate that the generic type parameter of an interface or delegate is covariant in T, you need to supply the out keyword.

However this is currently not possible for classes. I suggest to create an interface with a covariant generic type parameter, and let your class implement it.

As for covariance support in Silverlight 4: In the beta's it wasn't supported, I would need to check if they have implemented it in the release candidate. Edit: Apparently it is.

Edit2: There may be some confusion whether SL4 actually supports co- and contravariance for interfaces and delegates, due to the fact that some of the types in the BCL don't have the appropriate generic type modifiers set (IEnumerable<T>, Action<T>, Func<T>, ...).

Silverlight 5 addresses these issues: http://10rem.net/blog/2011/09/04/the-big-list-of-whats-new-or-improved-in-silverlight-5

The SL4 compiler does however support the in and out modifiers. The following compiles and works as expected:

interface IFoo<out T>
{
    T Bar { get; }
}
interface IBar<in T>
{
    void Add(T value);
}
delegate void ContravariantAction<in T>(T value);
delegate T CovariantFunc<out T>();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top