PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, November 3, 2022

[FIXED] Where does the C# specification clarify conversion of async lambda expressions to delegates?

 November 03, 2022     async-await, c#, lambda     No comments   

Issue

Microsoft's documentation states:

Any lambda expression can be converted to a delegate type. The delegate type to which a lambda expression can be converted is defined by the types of its parameters and return value. If a lambda expression doesn't return a value, it can be converted to one of the Action delegate types; otherwise, it can be converted to one of the Func delegate types.

(https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions)

This documentation, though, does not explain the behavior of async lambda expressions, specifically ones lacking any return statement, being converted to delegate values.

If you are trying to convert to a Func<Task>, the conversion succeeds.

If you are trying to convert to an Action, the conversion succeeds and the anonymous method emitted for the lambda is async void.

If both Action and Func<Task> are options, then the compiler selects Func<Task>.

This all makes sense, but where is it specified? Per the above paragraph, it shouldn't work this way. The paragraph quoted above doesn't allow for async methods that don't return a value having a return type of Task. I've done some searching and haven't found anything covering this. It must be out there, though, right? :-)


Solution

That language reference isn't really the spec, although it's reasonably "spec-like".

The relevant section of the draft C# 7 spec on the Microsoft site is here, based on the ECMA standard GitHub repo with the section here.

The relevant bullets in 10.7.1 for the conditions under which "an anonymous function F is compatible with a delegate type D" are:

  • If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (w.r.t §11) that would be permitted as a statement_expression (§12.7).
  • If the body of F is a block, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid block (w.r.t §12.3) in which no return statement specifies an expression.

Those are met for both Action and Func<Task> when considering an async lambda expression with no parameters and no return statements which specify expressions.

The fact that the conversion to Func<Task> is deemed better than the conversion to Action looks like it may be missing at the moment. I've raised a bug for this; it may be that there's something I've overlooked though (or that it wasn't specified in C# 7, and has been improved since then).



Answered By - Jon Skeet
Answer Checked By - Timothy Miller (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing