I have the following function with a delegate parameter that accepts a type of one interface and returns a task of another.
public void Bar(Func<IMessage, Task<IResult>> func)
{
throw new NotImplementedException();
}
I also have a function with a parameter as an instance of IMessage and returns a Task. Message and Result are implementations of IMessage and IResult respectively.
private Task<Result> DoSomething(Message m) { return new Task<Result>(() => new Result()); }
I receive an error when I pass DoSomething into Bar.
Bar(m => DoSomething((Message)m));
// Cannot convert type 'Task<Result>' to 'Task<IResult>'
Why won't Result implicitly convert into IResult?
I would imagine it's an issue with covariance. However, in this case, Result implements IResult. I've also tried to solve the covariance issue by creating an interface and marking TResult as covariant.
public interface IFoo<TMessage, out TResult>
{
void Bar(Func<TMessage, Task<TResult>> func);
}
But I get the error:
Invalid variance: The type parameter 'TResult' must be invariantly valid on
IFoo<TMessage, TResult>.Bar(Func<TMessage, Task<TResult>>). 'TResult' is covariant.
Now I'm stuck. I know I have an issue with covariance but I'm not sure how to solve it. Any ideas?
Edit: This question is specific to Tasks. I ran into this problem by implementing async await in my application. I came across this generic implementation and added a Task. Others may have the same issues during this type of conversion.
Solution: Here's the solution based on the answers below:
Func<Task<Result>, Task<IResult>> convert = async m => await m;
Bar(m => convert(DoSomething((Message)m)));