diff --git a/standard/conversions.md b/standard/conversions.md index 0144c757c..2d7761092 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -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. diff --git a/standard/expressions.md b/standard/expressions.md index 0ae84f22b..6f2b35b0d 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -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 @@ -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. @@ -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 parse = [X][return: Y] ([Z] s) > => (s is not null) ? int.Parse(s) : null; @@ -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 @@ -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 @@ -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 inferred @@ -6169,7 +6159,7 @@ Expression parseExpr = (string s) => int.Parse(s); // Expression> ``` -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: @@ -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`; - Otherwise, the delegate type is `System.Func`.