I'm really enjoying working with C# 5.0 asynchronous programming. However, there are a few places where updating old code to be consistent with the TAP model is causing problems for me.
Here's one of them - I'm not sure exactly why Task<TResult>
is not covariant in TResult, but it's causing problems for me when trying to update a covariant interface to move from a synchronous to an asychronous pattern:
Old code:
public interface IInitializable<out T> // ** out generic modifier **
{
/// <summary>
/// Boolean to indicate if class is ready
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// Calls for instance to be initialized using current parameters
/// Driver initialization can be done in the default constructor if desired
/// </summary>
T Initialize();
}
New code (won't compile):
public interface IAsyncInitializable<out T> // ** out generic modifier...broken **
{
/// <summary>
/// Boolean to indicate if class is ready
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// Calls for instance to be initialized using current parameters
/// Driver initialization can be done in the default constructor if desired
/// </summary>
Task<T> InitializeAsync(); // ** breaks because Task<TResult> is invariant in TResult **
}
Is there is a reasonable way around this without modifying my APIs too drastically? (Bonus: why is Task not covariant?). There's no IAwaitable interface, but I suppose I could make one and create an extension method that converts to a wrapped, covariant, awiatable task object. Or am I doing it wrong?