为什么带有不变类型参数的泛型中带有协变类型参数的嵌套泛型不能编译的原因是什么?

时间:2018-11-15 12:56:17

标签: c# .net generics compiler-errors covariance

以下是一些伴随我的问题的代码:

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>'

因此,如果IReadOnlyCollection<T>T上是协变的,而Task<T>T上是不变的,则Task<IReadOnlyCollection<IFirmEntity>>无效,即使看起来应该如此。

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


此外,作为一个旁注,下面的代码可以正常工作,但是,除非我理解不正确,否则我假设编译器足够聪明,可以评估异步/等待状态机中使用的协方差:< / p>

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

0 个答案:

没有答案
相关问题