Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ Specifically, an anonymous function `F` is compatible with a delegate type `D`

- If `F` contains an *anonymous_function_signature*, then `D` and `F` have the same number of parameters.
- If `F` does not contain an *anonymous_function_signature*, then `D` may have zero or more parameters of any type, as long as no parameter of `D` is an output parameter.
- If `F` has an explicitly typed parameter list, each parameter in `D` has the same modifiers as the corresponding parameter in `F` and an identity conversion exists between the corresponding parameter in `F`.
- If `F` has an explicitly typed parameter list, each parameter in `D` has the same modifiers as the corresponding parameter in `F`, ignoring `params` modifiers and default values, and an identity conversion exists between the corresponding parameter in `F`.
- If `F` has an implicitly typed parameter list, `D` has no reference or output parameters.
- If `F` has an explicit return type, an identity conversion shall exist from the return type of `F` to the return type of `D`.
- If the body of `F` is an expression, and *either* `D` has a void return type *or* `F` is async and `D` has a `«TaskType»` return type ([§15.14.1](classes.md#15141-general)), 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 [§12](expressions.md#12-expressions)) that would be permitted as a *statement_expression* ([§13.7](statements.md#137-expression-statements)).
Expand Down
34 changes: 12 additions & 22 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5618,22 +5618,7 @@ anonymous_function_signature
;

explicit_anonymous_function_signature
: '(' explicit_anonymous_function_parameter_list? ')'
;

explicit_anonymous_function_parameter_list
: explicit_anonymous_function_parameter
(',' explicit_anonymous_function_parameter)*
;

explicit_anonymous_function_parameter
: attributes? 'scoped'? anonymous_function_parameter_modifier? type identifier
;

anonymous_function_parameter_modifier
: 'ref'
| 'out'
| 'in'
: '(' parameter_list? ')'
;

implicit_anonymous_function_signature
Expand Down Expand Up @@ -5670,6 +5655,10 @@ A non-`static` local function or non-`static` anonymous function can capture sta
> *Note*: A `static` anonymous function is not required to produce the same delegate instance on each evaluation. See [§10.7.2](conversions.md#1072-evaluation-of-anonymous-function-conversions-to-delegate-types). *end note*
<!-- markdownlint-enable MD028 -->

A *lambda_expression* shall not contain any *parameter_modifier*s with the `this` modifier.

An *anonymous_method_expression* shall not contain any *default_argument*s or *parameter_array*s.

When recognising an *anonymous_function_body* if both the *null_conditional_invocation_expression* and *expression* alternatives are applicable then the former shall be chosen.

> *Note*: The overlapping of, and priority between, alternatives here is solely for descriptive convenience; the grammar rules could be elaborated to remove the overlap. ANTLR, and other grammar systems, adopt the same convenience and so *anonymous_function_body* has the specified semantics automatically. *end note*
Expand Down Expand Up @@ -5731,6 +5720,8 @@ A *block* body of an anonymous function is always reachable ([§13.2](statements
> delegate (int x) { return x + 1; } // Anonymous method expression
> static delegate (int x) { return x + 1; } // static anonymous method expression
> delegate { return 1 + 1; } // Parameter list omitted
> var addWithDefault = (int addTo = 2) => addTo + 1;
> var counter = (params int[] xs) => xs.Length;
> var concat = string ([DisallowNull] string a, [DisallowNull] string b) => a + b;
> Func<string, int?> parse = [X][return: Y] ([Z] s)
> => (s is not null) ? int.Parse(s) : null;
Expand All @@ -5748,6 +5739,7 @@ The behavior of *lambda_expression*s and *anonymous_method_expression*s is the s
- Only *lambda_expression*s have conversions to compatible expression tree types ([§8.6](types.md#86-expression-tree-types)).
- Only *lambda_expression* parameters may contain ‘scoped’.
- Only *lambda_expression*s may have *attributes* and explicit return types.
- An *anonymous_method_expression* may not contain any *default_argument*s or *parameter_array*s.

The contextual keyword `var` shall not be used as an explicit return type in a *lambda_expression*.

Expand All @@ -5761,9 +5753,7 @@ The *anonymous_function_signature* of an anonymous function defines the names an

If an anonymous function has an *explicit_anonymous_function_signature*, then the set of compatible delegate types and expression tree types is restricted to those that have the same parameter types and modifiers in the same order ([§10.7](conversions.md#107-anonymous-function-conversions)). In contrast to method group conversions ([§10.8](conversions.md#108-method-group-conversions)), contra-variance of anonymous function parameter types is not supported. If an anonymous function does not have an *anonymous_function_signature*, then the set of compatible delegate types and expression tree types is restricted to those that have no output parameters.

Note that an *anonymous_function_signature* cannot include a parameter array. Nevertheless, an *anonymous_function_signature* may be compatible with a delegate type whose parameter list contains a parameter array.

Note also that conversion to an expression tree type, even if compatible, may still fail at compile-time ([§8.6](types.md#86-expression-tree-types)).
Note that conversion to an expression tree type, even if compatible, may still fail at compile-time ([§8.6](types.md#86-expression-tree-types)).

### 12.22.3 Anonymous function bodies

Expand Down Expand Up @@ -6153,7 +6143,7 @@ object parse4 = (string s) => int.Parse(s);
Delegate parse5 = (string s) => int.Parse(s);
```

A method group has a natural type if all candidate methods (including extension methods) in the method group have a common signature.
A method group has a natural type if all candidate methods (including extension methods) in the method group have a common signature including default values and `params` modifiers.

```csharp
var read = Console.Read; // Just one overload; Func<int> inferred
Expand All @@ -6169,7 +6159,7 @@ Expression parseExpr = (string s) => int.Parse(s);
// Expression<Func<string, int>>
```

The natural type of an anonymous function expression or method group is called an ***anonymous function type***. An anonymous function type represents a method signature: the parameter types and ref kinds, and the return type and ref kind. Anonymous function expressions or method groups with the same signature have the same anonymous function type.
The natural type of an anonymous function expression or method group is called an ***anonymous function type***. An anonymous function type represents a method signature: the parameter types and ref kinds, default values, `params` modifiers, and the return type and ref kind. Anonymous function expressions or method groups with the same signature have the same anonymous function type.

Anonymous function types are used in a few specific contexts only:

Expand All @@ -6181,7 +6171,7 @@ An anonymous function type exists only at compile time.

The delegate type for the anonymous function or method group with parameter types `P1, ..., Pn` and return type `R` is, as follows:

- If any parameter or return value is not by value, or there are more than 16 parameters, or any of the parameter types or return type are not valid type arguments (e.g., `(int* p) => { }`), then the delegate is a synthesized `internal` anonymous delegate type with a signature that matches the anonymous function or method group, and with parameter names `arg1, ..., argn`, or `arg` if a single parameter;
- If any parameter or return value is not by value, or any parameter is optional or `params`, or there are more than 16 parameters, or any of the parameter types or return type are not valid type arguments (e.g., `(int* p) => { }`), then the delegate is a synthesized `internal` anonymous delegate type with a signature that matches the anonymous function or method group, and with parameter names `arg1, ..., argn`, or `arg` if a single parameter;
- If `R` is `void`, then the delegate type is `System.Action<P1, ..., Pn>`;
- Otherwise, the delegate type is `System.Func<P1, ..., Pn, R>`.

Expand Down
Loading