Cannot convert type 'Task<Derived>' to 'Task<Interface>'

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)));

Solution 1:

C# does not allow variance on classes, only interfaces and delegates that are parameterized with reference types. Task<T> is a class.

This is somewhat unfortunate, as Task<T> is one of those rare classes that could be made safely covariant.

However it is easy enough to convert a Task<Derived> to a Task<Base>. Just make a helper method / lambda that takes a Task<Derived> and returns Task<Base>, await the passed-in task, and return the value cast to Base. The C# compiler will take care of the rest. Of course you lose referential identity, but you weren't ever going to get that with a class.

Solution 2:

It seems like there's got to be a cleaner way of doing this, but it is possible to create a wrapping task of the correct type. I introduced a new function called GeneralizeTask().

Task<TBase> GeneralizeTask<TBase, TDerived>(Task<TDerived> task) 
    where TDerived : TBase 
{
    var newTask = new Task<TBase>(() => {
        if (task.Status == TaskStatus.Created) task.Start();
        task.Wait();
        return (TBase)task.Result;
    });
    return newTask;
}

Edit:

As @EricLippert points out, this can be simplified significantly. I first tried to find such a way to implement this method, but couldn't find one that compiled. As it turned out, the real solution was even simpler than I imagined.

async Task<TBase> GeneralizeTask<TBase, TDerived>(Task<TDerived> task) 
    where TDerived : TBase 
{
    return (TBase) await task;
}

You can then invoke Bar() like this.

Bar(m => GeneralizeTask<IResult, Result>(DoSomething((Message)m)));

Solution 3:

I am using another version of GeneralizeTask, which is stated by @Recursive, on Asp Net Core Framework. Here it is:

public static Task<TBase> GeneralizeTask<TDerived, TBase>(this Task<TDerived> task, CancellationToken cancellationToken = default) 
 where TBase : class 
 where TDerived : TBase
{
    var result = task.ContinueWith(t => (TBase)t.Result, cancellationToken);
    return result;
}