C# 由于使用任务,使泛型函数异步在类型转换时失败<;T>;

C# 由于使用任务,使泛型函数异步在类型转换时失败<;T>;,c#,type-inference,C#,Type Inference,以下是给定接口和类的结构: public abstract class Entity { } public class Group : Entity { } public interface ICollectionPage<T> { } public interface IGraphServiceGroupsCollectionPage : ICollectionPage<Group> { } 但如果尝试使用async方法,则会出现类型转换错误: var coll

以下是给定接口和类的结构:

public abstract class Entity
{ }

public class Group : Entity
{ }

public interface ICollectionPage<T>
{ }

public interface IGraphServiceGroupsCollectionPage : ICollectionPage<Group>
{ }
但如果尝试使用async方法,则会出现类型转换错误:

var collectionPageTask = (Task<IGraphServiceGroupsCollectionPage>)null;
var groupsFromAsync = GetAllAsync<IGraphServiceGroupsCollectionPage>(collectionPageTask);

为了实现这一点,我们需要一个扩展方法,它将
任务
作为输入,并返回
任务
。通过尝试构建此扩展方法,我们遇到了上述问题,并将其归结为上述示例。

您需要使
任务
参数更通用

private static Task<IEnumerable<T>> GetAllAsync<T,T2>(Task<T> collectionTask)
   where T : ICollectionPage<T2>
   where T2 : Entity
{
   throw new NotImplementedException();
}
私有静态任务GetAllAsync(任务收集任务)
其中T:ICollectionPage
其中T2:实体
{
抛出新的NotImplementedException();
}

var collectionPageTask=(Task)null;
var groupsFromAsync=GetAllAsync(collectionPageTask);

您需要使
任务
参数更通用

private static Task<IEnumerable<T>> GetAllAsync<T,T2>(Task<T> collectionTask)
   where T : ICollectionPage<T2>
   where T2 : Entity
{
   throw new NotImplementedException();
}
私有静态任务GetAllAsync(任务收集任务)
其中T:ICollectionPage
其中T2:实体
{
抛出新的NotImplementedException();
}

var collectionPageTask=(Task)null;
var groupsFromAsync=GetAllAsync(collectionPageTask);

问题在于
任务(作为一个类)是不变的。根据问题中的评论:

IGraphServiceGroupsCollectionPage
实现了
ICollectionPage
,该方法可用于
任务

您希望
任务
任务
兼容。事实并非如此。你可以很简单地说:

task1=null;
任务task2=task1;
这会产生以下错误:

错误:无法将类型“System.Threading.Tasks.Task”隐式转换为“System.Threading.Tasks.Task”

此外,本电话:

GetAllAsync(collectionPageTask)
。。。为
T
提供了一个显式类型参数
IGraphServiceGroupsCollectionPage
,该参数的类型为
ICollectionPage
,因此编译器试图将该参数转换为
任务


问题是
任务(作为一个类)是不变的。根据问题中的评论:

IGraphServiceGroupsCollectionPage
实现了
ICollectionPage
,该方法可用于
任务

您希望
任务
任务
兼容。事实并非如此。你可以很简单地说:

task1=null;
任务task2=task1;
这会产生以下错误:

错误:无法将类型“System.Threading.Tasks.Task”隐式转换为“System.Threading.Tasks.Task”

此外,本电话:

GetAllAsync(collectionPageTask)
。。。为
T
提供了一个显式类型参数
IGraphServiceGroupsCollectionPage
,该参数的类型为
ICollectionPage
,因此编译器试图将该参数转换为
任务


.

返回类型不同,这与异步和任务无关。错误抱怨将
IGraphServiceGroupsCollectionPage
转换为
ICollectionPage
为什么
GetAllAsync
接受
Task collectionTask
而不是
ICollectionPage
?为什么不等待前面的任务并将结果传递给方法?即使您使用了
.ContinueWith
,您也会将结果传递给任何后续方法。是的,您将无法将参数强制放入“任务”中,就像那样异步调用没有区别。
async
关键字不会影响任何东西,它只是一个标记,告诉编译器该方法可以使用
wait
。不过,将任务作为参数传递给另一个方法的情况极为罕见。为什么要这样做?忘记异步,这是一个类型问题而不是TPL问题返回类型不同,这与异步和任务没有什么关系。错误抱怨将
IGraphServiceGroupsCollectionPage
转换为
ICollectionPage
为什么
GetAllAsync
接受
Task collectionTask
而不是
ICollectionPage
?为什么不等待前面的任务并将结果传递给方法?即使您使用了
.ContinueWith
,您也会将结果传递给任何后续方法。是的,您将无法将参数强制放入“任务”中,就像那样异步调用没有区别。
async
关键字不会影响任何东西,它只是一个标记,告诉编译器该方法可以使用
wait
。不过,将任务作为参数传递给另一个方法的情况极为罕见。你为什么要这样做?忘记异步,这是一个类型问题而不是TPL问题。我的答案是“这就是为什么它目前无法编译”。@JonSkeet-alley-oop,slamdunkYes,这是有效的,但现在类型推断已经消失了。因此,如果您试图调用此方法而不显式指定泛型参数,则会失败。@Oliver这确实是问题所在,请参阅Jon的解释,为什么不能以其他方式执行此操作感谢您提供了“这是要做的事”-我的回答提供了“这就是它目前无法编译的原因”。@JonSkeet alley oop,slamdunkYes,这很有效,但是现在类型推断已经不存在了。因此,如果您试图调用此方法而不显式指定泛型参数,则会失败。@Oliver这确实是问题所在,请参阅jons解释,否则无法执行此操作
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();
private static Task<IEnumerable<T>> GetAllAsync<T,T2>(Task<T> collectionTask)
   where T : ICollectionPage<T2>
   where T2 : Entity
{
   throw new NotImplementedException();
}
var collectionPageTask = (Task<IGraphServiceGroupsCollectionPage>)null;
var groupsFromAsync = GetAllAsync<IGraphServiceGroupsCollectionPage,Entity>(collectionPageTask);