среда, 17 февраля 2010 г.

Co/Contravariance for .NET 2.0+

CLR supports generic variance for generic interfaces and delegates since version 2.0.

ECMA 335:

The CLI supports covariance and contravariance of generic parameters, but only in the signatures of interfaces and delegate classes. Suppose we have a generic interface, which is covariant in its one generic parameter; e.g., IA`1<+T>. Then all instantiations satisfy IA`1<GenArgB> := IA`1<GenArgA>, so long as GenArgB := GenArgA using the notion from assignment compatibility. So, for example, an instance of type IA`1<string> can be assigned to a local of type type IA`1<object>.

Generic contravariance operates in the opposite sense: supposing that we have a contravariant interface IB`1<-T>, then IB`1<GenArgB> := IB`1<GenArgA>, so long as GenArgA := GenArgB.

in spite of this, co/contravariance features  were only partially exposed for the users of mainstream languages. C# 2.0 add support only for covariance and contravariance in delegates.  C# 4.0 makes one step further: both interfaces and delegates are supported and now it is possible to annotate generic parameter to be either covariant (out) or contravariant (in) and compiler will verify that all usages of this parameter are correct corresponding to the annotation.

For example:

public interface IMyComparer<in T>
{
// contravariant generic parameter
int Compare(T a, T b);
}

public interface IFactory<out T>
{
// covariant generic parameter
T Create();
}

public class MyComparer<T> : IMyComparer<T>
{
public int Compare(T a, T b)
{
return 0;
}
}

public class Factory<T> : IFactory<T>
{
public T Create()
{
return default(T);
}
}

// usage

IMyComparer<string> s = new MyComparer<object>();
IFactory<object> p = new Factory<string>();

Very nice feature! And it doesn’t require .NET 4.0 for execution, runtime already supports variance and C# compiler makes all remaining job.

Note:, all standard interfaces (IEnumerable<T>, IEnumerator<T>, IQueryable<T>, IGrouping<TK, TV>, IEqualityComparer<T>, IComparer<T>, IComparable<T> ) and delegates (Action<>, Func<T>, Predicate<T>, Comparison<T>, Converter<TIn, TOut>) shall not be accessible, since annotated versions are located in 4.0 assemblies.

Other compiler features that are accessible from VS 2010 for .NET 2.0+

  • optional parameters
  • named parameters
class Program
{
static void Main(string[] args)
{
Run(b : "value", a : 10);
}

public static void Run(int a, string b)
{
Console.WriteLine("a = {0}, b = {1}", a, b);
}
}

Комментариев нет:

Отправить комментарий

 
GeekySpeaky: Submit Your Site!