views:

92

answers:

2

Possible Duplicates:
Why isn't there generic variance for classes in C# 4.0?
Why does C# (4.0) not allow co- and contravariance in generic class types?

The new .NET 4.0 co- and contravariance for generic type arguments only works for interfaces and delegates. What is the reason for not supporting it for classes too?

+7  A: 

For type safety, C# 4.0 supports covariance/contravariance ONLY for type parameters marked with in or out.

If this extended to classes, you'd also have to mark type parameters with in our out and this would end up being very restrictive. This is most likely why the designers of the CLR chose not to allow it. For instance, consider the following class:

public class Stack<T>
{
  int position;
  T[] data = new T[100];
  public void Push (T obj)   { data[position++] = obj;  }
  public T Pop()             { return data[--position]; }
}

It would be impossible to annotate T as either in our out, because T is used in both input and output positions. Hence this class could never covariant or contravariant - even in C# supported covariance/contravariant type parameters for classes.

Interfaces solve the problem nicely. We can have define two interfaces as follows, and have Stack implement both:

public interface IPoppable<out T> { T Pop(); }
public interface IPushable<in T> { void Push (T obj); }

Note that T is covariant for IPoppable and contravariant for IPushable. This means T can be either covariant or contravariant - depending on whether you cast to IPoppable or IPushable.

Another reason that covariance/contravariance would be of limited use with classes is it would rule out using type parameters as fields - because fields effectively allow both input and output operations. In fact, it would be hard to write a class that does anything useful at all with a type parameter marked as in or out. Even the simplest case of writing a covariant Enumerable implementation would present a challenge - how would you get source data into the instance to begin with?

Joe Albahari
+1  A: 

The .NET team along with the C# and VB.NET team has limited resources, the work they have done on co- and contravariance solves most of the real world problem. Type systems are very complex to get right – a solution that works in 99.9999% of cases is not good enough if it leads to unsafe code in the other cases.

I don’t think the cost/time of supporting co- and contravariance specs (e.g. “in”/”out”) on class methods is of a great enough value. I can see very few cases when they would be useable – due to the lack of multiply class inheritance.

Would you rather had waited for another 6 months for .net so as to get this support?


Another way to think of this is that in .net

  • Interfaces / delegates – are used to model the conceptual type system of an application
  • Class are used to implement the above types
  • Class inheritance is used to reduce code duplication while doing the above
  • co- and contravariance is about the conceptual type system of an application
Ian Ringrose

related questions