繁体   English   中英

为什么我不能返回任务<ienumerable<out t> > 无需让我的方法异步并使用 await </ienumerable<out>

[英]Why can't I return a Task<IEnumerable<out T>> without making my method async and using await

目前我有一个签名为public Task<IEnumerable<Descriptor>> GetAllDescriptors()的方法,其中Descriptor是我创建的 public class。 然后我在这个方法中调用了各种任务,如下所示:

var allDescriptors = Task.WhenAll(GetMovieDescriptorsAsync, GetSongDescriptorsAsync);

由于GetMovieDescriptorsAsyncGetSongDescriptorsAsync都返回Task<Descriptor>我知道allDescriptors的变量类型是Task<Descriptor[]>这很好。 但是,如果我尝试return allDescriptors ,则会收到错误消息:

Cannot implicitly convert type 'System.Threading.Tasks.Task<Descriptor[]>' to 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Descriptor>>'

但是,如果我将方法签名更改为public async Task<IEnumerable<Descriptor>> GetAllDescriptors()然后我尝试return await allDescriptors它工作并且我在调用 function 中获得所需的<IEnumerable<CompletionInfo>

var descriptors = await GetAllDescriptors();

为什么会这样,我怎样才能返回预期的IEnumerable<Descriptor>而不必使用异步和等待?

Task.WhenAll<T>返回一个Task<T[]> ,所以在你的情况下

Task<IEnumerable<Decsriptor>[]> allDescriptors = Task.WhenAll(GetMovieDescriptorsAsync, GetSongDescriptorsAsync);

allDescriptors是一个Task<IEnumerable<Decsriptor>[]> ,它是一个包装了描述符枚举数组的任务。

首要任务是获取任务结果:

IEnumerable<Descriptor>[] taskResults = allDescriptors.Result;

然后将数组taskResults中的每个IEnumerable<Descriptor>合并到一个平面列表中:

IEnumerable<Descriptor> descriptors = taskResults.SelectMany(value => value);

您描述的问题(和解决方案)是covariance IEnumerable<out T>是协变接口,这意味着您可以将IEnumerable<string>分配给 IEnumerable IEnumerable<object>

但是, Task<TResult>不是协变的。 这意味着您不能返回更具体的 object 来代替通用定义(如果您有Task<object> ,则不能返回Task<string> )。

现在,添加asyncawait会使编译器对此有所不同。 简化, async取消了Task声明,因此它返回TResult 如果你有一个方法object Foo() ,你可以在这个方法中使用return "" 因为方法的返回类型总是协变的。

总而言之, async Task<TResult>TResult类似,因此您可以通过这种方式返回更具体的对象。 但是, Task<TResult>是一种非协变类型,因此您必须准确返回指定的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM