首页 > 解决方案 > 具有不变类型参数的泛型中具有协变类型参数的嵌套泛型无法编译的原因是什么?

问题描述

这是我的问题的一些代码:

interface IFirmEntity { }
interface IClient : IFirmEntity { }

class Repository
{
    public Task<ReadOnlyCollection<IClient>> GetClientsAsync()
    {
        throw new NotImplementedException();
    }

    public ReadOnlyCollection<IClient> GetClients()
    {
        throw new NotImplementedException();
    }
}

现在,如果我编写以下代码,我会收到如下所述的错误:

var repo = new Repository();

// works b/c of covariance on IReadOnlyCollection<T>
IReadOnlyCollection<IFirmEntity> a1 = repo.GetClients();

// does not work b/c of invariance of Task<T>
Task<IReadOnlyCollection<IFirmEntity>> a2 = repo.GetClientsAsync();

(CS0029) 无法将类型“System.Threading.Tasks.Task>”隐式转换为“System.Threading.Tasks.Task>”

因此, where IReadOnlyCollection<T>is covariant onT并且Task<T>is invariant on TTask<IReadOnlyCollection<IFirmEntity>>即使看起来应该起作用,也不起作用。

嵌套泛型与协方差结合无法编译的技术原因是什么?


另外,作为旁注,下面的代码工作得很好,但是,除非我理解错了,否则我假设编译器足够聪明,可以评估 async/await 状态机中使用的协方差:

var mech = new SomeMechanism();

// this works just fine.
Task<IReadOnlyCollection<IFirmEntity>> a3 = 
    mech.DoAsync(async () => await repo.GetClientsAsync()); // No error.

class SomeMechanism
{
    public Task DoAsync(Func<Task<IReadOnlyCollection<IFirmEntity>>> someOperation) 
        => throw new NotImplementedException();
}

标签: c#.netgenericscompiler-errorscovariance

解决方案


推荐阅读