我能做到:
public static IEnumerable<string> Do()
{
return new List<string>();
}
但是,如果我回复任务,我不允许做同样的事情:
public static Task<IEnumerable<string>> DoTask()
{
return Task.Factory.StartNew(() =>
{
return new List<string>(); //no no
});
}
我在.NET 4.0中实现了异步存储库并遇到了这个问题。我只是好奇为什么编译器在包装在一个任务中时无法将我的List
强制转换?当然,我的工作只是抛出AsEnumerable
,但我想知道为什么存在这种限制?
答案 0 :(得分:4)
从Task<List<string>>
转换为Task<IEnumerable<string>>
需要Task<T>
为协变且内部类型为接口。在这种情况下都不是这样,所以不允许转换。
明显的修复 - 通过显式指定lambda的类型将Task
的结果转换为必要的类型
return Task.Factory.StartNew((Func<IEnumerable<string>>)
(() =>
{
return new List<string>();
}));
或隐式地通过投射结果:
return (IEnumerable<string>)new List<string>();
详细信息 - Covariance and Contravariance FAQ
为什么Task<List<string>>
是TaskFactory.StartNew调用的结果:
传递给StartNew
调用的Lambda没有明确指定其类型,因此编译器会从return
语句中推断出它的返回类型。由于return
明确指出new List...
整体类型的lambda在这种情况下等同于Func<List<string>>
。