I bumped into this C# compiler error and while I’m ok with the compiler not being able to infer the type of the lambda the error message seems wrong. Here’s the relevant piece of code:
Func<object> lambda = async () => { return await Task.FromResult(1); };
and here’s the compiler error:
error CS4010: Cannot convert async lambda expression to delegate type ‘
System.Func<object>‘. An async lambda expression may returnvoid,TaskorTask<T>, none of which are convertible to ‘System.Func<object>‘.
The part I don’t quite understand is the last sentence. The lambda is indeed returning Task<int>, but why does the compiler think that it should try to convert it to System.Func<object>?
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 which means that this works just fine instead:
Func<object> lambda = new Func<Task<int>>(async () => { return await Task.FromResult(1); });
I believe the error message is poorly worded. It’s trying to derive a return type for the lambda (which can be
void,Task, orTask<T>), and convert the lambda toFunc<object>. I recommend that you raise an issue on Microsoft Connect requesting a clearer error message.True, but the compiler doesn’t determine the type of lambda expressions until “later” than most expressions. The compiler doesn’t see
Func<Task<int>>(it just sees a lambda expression taking no arguments and returningTaskorTask<int>), and so it won’t use generic delegate variance.I’m hoping that Eric Lippert will do a blog post on how
asynclambda expressions are resolved, particularly in the case of method overload selection.