2012-11-06 53 views
2

我碰到了这个C#编译器错误,虽然我确定编译器不能推断lambda的类型,但错误消息看起来不对。下面是相关的代码:异步lambda类型推断错误的C#编译器错误信息

Func<object> lambda = async() => { return await Task.FromResult(1); }; 

和这里的编译器错误:

error CS4010: Cannot convert async lambda expression to delegate type ' System.Func<object> '. An async lambda expression may return void , Task or Task<T> , none of which are convertible to ' System.Func<object> '.

我不太明白的部分是最后一句。 lambda确实返回Task<int>,但为什么编译器认为它应该尝试将其转换为System.Func<object>?另一方面,如果错误信息试图传达的是System.Func<Task<int>>不能被分配给System.Func<object>,但似乎并不是这种情况,这要归功于泛型委托协方差,这意味着它可以正常工作:

Func<object> lambda = new Func<Task<int>>(async() => { return await Task.FromResult(1); }); 
+0

编译器应该将它转换为'System.Func ',因为这是你声明变量的方式,它与异步代理不兼容。 –

+1

*异步方法的返回类型必须为空,任务或任务 * –

回答

2

The lambda is indeed returning Task<int> , but why does the compiler think that it should try to convert it to System.Func<object> ?

我认为错误消息的措辞不当。它试图为lambda导出返回类型(可以是void,TaskTask<T>),并将转换为lambdaFunc<object>。我建议您在Microsoft Connect上提出一个问题,要求提供更清晰的错误消息。

On the other hand, if what the error message is trying to convey is that System.Func<Task<int>> cannot be assigned to System.Func<object> , that doesn't seem to be the case thanks to generic delegate covariance

确实如此,但编译器不会确定lambda表达式的类型,直到“晚于”才比大多数表达式为止。编译器没有看到Func<Task<int>>(它只是看到一个不带参数的lambda表达式,并返回TaskTask<int>),所以它不会使用泛型委托方差。

我希望Eric Lippert会写一篇关于async lambda表达式如何解决的博客文章,特别是在方法过载选择的情况下。

+0

谢谢斯蒂芬,误导性的错误信息正是我所关心的。只是想在报告之前获得一些快速反馈,我刚刚在[这里](https://connect.microsoft.com/VisualStudio/feedback/details/770315/wrong-c-compiler-error-message-on-async -Lambda型推理)。 – Simone