【发布时间】:2020-09-04 08:29:33
【问题描述】:
这是给定接口和类的结构:
public abstract class Entity
{ }
public class Group : Entity
{ }
public interface ICollectionPage<T>
{ }
public interface IGraphServiceGroupsCollectionPage : ICollectionPage<Group>
{ }
这里有两种使用这些接口的方法。一个是同步的,另一个是异步的,你使用Task<T> 作为参数:
private static Task<IEnumerable<T>> GetAllAsync<T>(Task<ICollectionPage<T>> collectionTask)
where T : Entity
{
throw new NotImplementedException();
}
private static Task<IEnumerable<T>> GetAll<T>(ICollectionPage<T> collectionTask)
where T : Entity
{
throw new NotImplementedException();
}
如果我们尝试在代码中使用同步方法,一切都会按预期工作:
var collectionPage = (IGraphServiceGroupsCollectionPage)null;
var groups = GetAll(collectionPage);
但是如果我们尝试使用 async 方法,就会出现类型转换错误:
var collectionPageTask = (Task<IGraphServiceGroupsCollectionPage>)null;
var groupsFromAsync = GetAllAsync<IGraphServiceGroupsCollectionPage>(collectionPageTask);
错误 CS1503:参数 1:无法从 'System.Threading.Tasks.Task
' 转换为 'System.Threading.Tasks.Task >'
知道如何在异步调用中避免这个错误吗?
完整代码:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public interface IGraphServiceClient
{
}
public abstract class Entity
{
}
public class Group : Entity
{
}
public interface ICollectionPage<T>
{
}
public interface IGraphServiceGroupsCollectionPage : ICollectionPage<Group>
{
}
public class Program
{
private static Task<IEnumerable<T>> GetAllAsync<T>(Task<ICollectionPage<T>> collectionTask)
where T : Entity
{
throw new NotImplementedException();
}
private static Task<IEnumerable<T>> GetAll<T>(ICollectionPage<T> collectionTask)
where T : Entity
{
throw new NotImplementedException();
}
static void Main(string[] args)
{
var collectionPage = (IGraphServiceGroupsCollectionPage)null;
var groups = GetAll(collectionPage);
var collectionPageTask = (Task<IGraphServiceGroupsCollectionPage>)null;
var groupsFromAsync = GetAllAsync<IGraphServiceGroupsCollectionPage>(collectionPageTask);
}
}
更新原因:您为什么要这样做?
原因很简单。第一步,我们想为另一个异步方法编写一个扩展方法。此方法具有以下签名:
public interface IGraphServiceUsersCollectionRequest
{
public Task<IGraphServiceGroupsCollectionPage> GetAsync();
}
当我们喜欢这样称呼它时,我们喜欢这样做:
var request = (IGraphServiceUsersCollectionRequest)null;
var result = await request.GetAsync().GetAllAsync();
为了让它工作,我们需要一个扩展方法,它接受一个Task<IGraphServiceGroupsCollectionPage> 作为输入并返回一个Task<IEnumerable<Group>>。通过尝试构建此扩展方法,我们遇到了上述问题,我们将其归结为上述示例。
【问题讨论】:
-
返回类型不同,这与async和Task关系不大。该错误抱怨将
IGraphServiceGroupsCollectionPage转换为ICollectionPage<IGraphServiceGroupsCollectionPage> -
为什么
GetAllAsync接受Task<ICollectionPage<T>> collectionTask而不是ICollectionPage<T>?为什么不await之前的任何任务并将结果传递给方法?即使您使用.ContinueWith,您也会将结果传递给任何后续方法 -
是的,你不能像那样将参数强制放入`Task
-
异步调用没有区别。
async关键字不会影响任何东西,它只是一个标记,告诉编译器该方法可以使用await。但是,将任务作为参数传递给另一个方法是非常罕见的。你为什么要这样做? -
忘记异步,这是打字问题而不是 TPL 问题
标签: c# type-inference