无法转换类型'Task< Derived>'到“任务<接口>” [英] Cannot convert type 'Task<Derived>' to 'Task<Interface>'

查看:69
本文介绍了无法转换类型'Task< Derived>'到“任务<接口>”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下带有委托参数的函数,该参数接受一个接口的类型并返回另一个接口的任务。

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

我也有一个函数,该函数的参数为​​<$ c $的实例c> IMessage 并返回一个任务。 Message Result IMessage 和<$ c的实现

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

将DoSomething传递到Bar时会收到错误消息。

I receive an error when I pass DoSomething into Bar.

Bar(m => DoSomething((Message)m));
// Cannot convert type 'Task<Result>' to 'Task<IResult>'

为什么 Result 不能隐式转换为 IResult

Why won't Result implicitly convert into IResult?

我想这是协方差问题。但是,在这种情况下, Result 实现了 IResult 。我还尝试通过创建一个接口并将 TResult 标记为协变来解决协方差问题。

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

但是我得到了错误:


无效方差:类型参数 TResult必须始终对 IFoo< TMessage,TResult> .Bar(Func< TMessage,Task< ; TResult>>)
TResult是协变的。

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?

编辑:此问题特定于任务。我在应用程序中实现了 async await 遇到了这个问题。我遇到了这个通用实现,并添加了 Task 。其他人在这种类型的转换过程中可能会遇到相同的问题。

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


推荐答案

C#不允许类的变化,仅接口和用引用类型参数化的委托。 Task< T> 是一个类。

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

这有点不幸,因为 Task< T> 是可以可以安全地进行协变的那些稀有类之一。

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

但是它很容易将 Task< Derived> 转换为 Task< Base> 。只需创建一个辅助方法/ lambda,使其接受 Task< Derived> 并返回 Task< Base> ,等待通过-in任务,并将值强制转换为 Base 。 C#编译器将负责其余的工作。当然,您会失去参照身份,但是您永远都不会在课堂上得到这种身份。

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.

这篇关于无法转换类型'Task&lt; Derived&gt;'到“任务&lt;接口&gt;”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆