从 ICollection<T> 到 IEnumerable<T> 的隐式转换

Implicit conversion from ICollection<T> to IEnumerable<T>

ICollection<T> 实现 IEnumerable<T> 这样的东西是有效的:

ICollection<Computer> Computers {get; set;}
IEnumerable<Computer> Retrieve() => Computers;

但为什么编译器声明在以下情况下不能进行隐式转换?

ICollection<Computer> Computers {get; set;}

// Error below
// Cannot implicitly convert from Task<ICollection<Computer>> to Task<IEnumerable<Computer>>
Task<IEnumerable<Computer>> RetrieveAsync() => Task.FromResult(Computers);

为了让它工作,我需要调用 Task.FromResult(Computers.AsEnumerable())

问题是……为什么? ICollection<Computer> 显然也是一个 IEnumerable<Computer> 并且当它没有包含在 Task 中时隐式转换工作得很好,为什么将它包装在 Task 中会改变任何东西?

虽然 ICollection<Computer>IEnumerable<Computer>,但 Task<ICollection<Computer>> 不是 Task<IEnumerable<Computer>>

这是因为对于Task<TResult>TResult是不变的。

Covariance and Contravariance in generics

Johnathan Barclay 解释了为什么会出现此错误。如果想不调用AsEnumerable()就解决,可以在Taskclass:

中显式给FromResult方法的类型参数
Task<IEnumerable<Computer>> RetrieveAsync() => Task.FromResult<IEnumerable<Computer>>(Computers);

在线演示:https://dotnetfiddle.net/0hEnfY