Information Technology Reference
In-Depth Information
contravariant ( in ), and method return types are covariant ( out ). The BCL
updated many of their delegate definitions to include variance:
public delegate TResult Func < out TResult>();
public delegate TResult Func < in T, out TResult>(T arg);
public delegate TResult Func < in T1, T2, out TResult>(T1 arg1,
T2 arg2);
public delegate void Action < in T>(T arg);
public delegate void Action < in T1, in T2>(T1 arg1, T2 arg2);
public delegate void Action < in T1, in T2, T3>(T1 arg1,
T2 arg2, T3 arg3);
Again, this probably isn't too hard. But, when you mix them, things start
to get to be mind benders. You already saw that you cannot return invari-
ant interfaces from covariant interfaces. You can't use delegates to get
around the covariant and contravariant restrictions, either.
Delegates have a tendency to “flip” the covariance and contravariance in
an interface if you're not careful. Here are a couple examples:
public interface ICovariantDelegates <out T>
{
T GetAnItem();
Func <T> GetAnItemLater();
void GiveAnItemLater( Action <T> whatToDo);
}
public interface IContravariantDelegates < in T>
{
void ActOnAnItem(T item);
void GetAnItemLater( Func <T> item);
Action <T> ActOnAnItemLater();
}
I've named the methods in these interfaces specifically to show why it
works the way it does. Look closely at the ICovariantDelegate interface
definition. GetAnItemLater() is just a way to retrieve an item lazily. The
caller can invoke the Func<T> returned by the method later to retrieve a
value. T still exists in the output position. That probably still makes sense.
The GetAnItemLater() method probably is a bit more confusing. Here,
you're method takes an delegate that will accept a T object whenever you
call it. So, even though Action<in T> is covariant, its position in the
 
Search WWH ::




Custom Search