У меня есть следующая функция с параметром делегата, которая принимает тип одного интерфейса и возвращает задачу другого.
public void Bar(Func<IMessage, Task<IResult>> func)
{
throw new NotImplementedException();
}
У меня также есть функция с параметром в качестве экземпляра IMessage
и возвращает задачу. Message
и Result
являются реализациями IMessage
и IResult
соответственно.
private Task<Result> DoSomething(Message m) { return new Task<Result>(() => new Result()); }
Я получаю сообщение об ошибке при передаче DoSomething в Bar.
Bar(m => DoSomething((Message)m));
// Cannot convert type 'Task<Result>' to 'Task<IResult>'
Почему не будет Result
неявно конвертировать в IResult
?
Я бы подумал, что это проблема с ковариацией. Однако в этом случае Result
реализует IResult
. Я также попытался решить проблему ковариации, создав интерфейс и отметив TResult
как ковариантный.
public interface IFoo<TMessage, out TResult>
{
void Bar(Func<TMessage, Task<TResult>> func);
}
Но я получаю ошибку:
Неверная дисперсия: параметр типа "TResult" должен быть инвариантным действует на
IFoo<TMessage, TResult>.Bar(Func<TMessage, Task<TResult>>)
. "TResult" является ковариантным.
Теперь я застрял. Я знаю, что у меня проблема с ковариацией, но я не уверен, как ее решить. Любые идеи?
Изменить: этот вопрос относится к задачам. Я столкнулся с этой проблемой, выполнив async await
в своем приложении. Я столкнулся с этой общей реализацией и добавил Task
. Другие могут иметь одинаковые проблемы во время этого типа преобразования.
Решение: Здесь решение основано на ответах ниже:
Func<Task<Result>, Task<IResult>> convert = async m => await m;
Bar(m => convert(DoSomething((Message)m)));