首页 > 解决方案 > 由于使用 Task,使泛型函数异步在类型转换时失败

问题描述

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

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<RemotePowershell.IGraphServiceGroupsCollectionPage>' 转换为 'System.Threading.Tasks.Task<RemotePowershell.ICollectionPage<RemotePowershell.IGraphServiceGroupsCollectionPage>>'

关于如何在异步调用中避免此错误的任何想法?

完整代码:

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>>. 通过尝试构建此扩展方法,我们遇到了上述问题,我们将其归结为上述示例。

标签: c#type-inference

解决方案


您将需要使Task参数更通用。

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

推荐阅读