Tuesday, June 26, 2012

Generic Variance in C# 4.0

Although I’m not cool enough to actually go to PDC, I’ve been watching some of the things that have been announced. One of the things I’m most excited about is co- and contra-variance in generics, which is something that the CLR has lacked since generics were first introduced in 2.0. (Note: some of the examples on here are pulled from the excellent description of new features release by Microsoft.)

In versions of C# prior to 4.0, generics were invariant. For example, consider this simple type definition:

public class Foo<T>
{
  //...
}

Since the generic type parameter T was not constrained, the compiler understands that T should be treated as type object. That means that since a string is an object, a Foo<string> is functionally equivalent to a Foo<object>. However, because of generic invariance, ian instance of Foo<string> cannot be assigned to a variable of type Foo<object>.

C# 4.0 introduces the ability to declare covariant and contravariant generics. For example:

public class Foo<out T>
{
  //...
}

This class is covariant in T, meaning that if you create a Foo<string>, you can use it effectively as a Foo<object>, since a string is a subclass of object. The example given is the new IEnumerable<T> interface that comes with the BCL in C# 4.0:

public interface IEnumerable<out T> : IEnumerable
{
  IEnumerator<T> GetEnumerator();
}

public interface IEnumerator<out T> : IEnumerator
{
  bool MoveNext();
  T Current { get; }
}

Since these interfaces are covariant in T, an IEnumerable<string> can be used as an IEnumerable<object>. The same is true for List<T>, so you’ll be able to do this, which was previously impossible:

IList<string> strings = new List<string>();
IList<object> objects = strings;
Note, however, that you can only declare that your type is covariant for generic type parameters that appear in output positions — basically, return values.

Like the out keyword, you can also use the in keyword:

public interface IComparer<in T>
{
  int Compare(T left, T right);
}

Read more: Discord&Rhyme
QR: Inline image 1

Posted via email from Jasper-Net