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 @@ -930,7 +930,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 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)).
- If the body of `F` is a block, and *either* `D` has a void return type *or* `F` is async and `D` has a `«TaskType»` return type , 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 [§13.3](statements.md#133-blocks)) in which no `return` statement specifies an expression.
Expand Down
34 changes: 12 additions & 22 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5629,22 +5629,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 @@ -5677,6 +5662,10 @@ A non-`static` local function or non-`static` anonymous function can capture sta

Removing the `static` modifier from an anonymous function in a valid program does not change the meaning of the program.

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.

<!-- markdownlint-disable MD028 -->
Expand Down Expand Up @@ -5736,6 +5725,8 @@ A *block* body of an anonymous function is always reachable ([§13.2](statements
> async (t1,t2) => await t1 + await t2 // Async
> static delegate (int x) { return x + 1; } // 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 @@ -5753,6 +5744,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.

### 12.22.2 Anonymous function signatures

Expand All @@ -5762,9 +5754,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