Skip to content

Commit ae78b6e

Browse files
authored
Add ref readonly parameters feature
1 parent 230e59d commit ae78b6e

1 file changed

Lines changed: 26 additions & 7 deletions

File tree

standard/classes.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,7 +2296,7 @@ parameter_modifier
22962296
;
22972297
22982298
parameter_mode_modifier
2299-
: 'ref'
2299+
: ref_kind
23002300
| 'out'
23012301
| 'in'
23022302
;
@@ -2308,13 +2308,13 @@ parameter_array
23082308

23092309
The parameter list consists of one or more comma-separated parameters of which only the last may be a *parameter_array*.
23102310

2311-
A *fixed_parameter* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)); an optional `this` modifier; an optional `scoped` modifier; an optional `in`, `out`, `ref` modifier; a *type*; an *identifier*; and an optional *default_argument*. Each *fixed_parameter* declares a parameter of the given type with the given name. The `this` modifier designates the method as an extension method and is only allowed on the first parameter of a static method in a non-generic, non-nested static class. If the parameter is a `struct` type or a type parameter constrained to a `struct`, the `this` modifier may be combined with either the `ref` or `in` modifier, but not the `out` modifier. Extension methods are further described in [§15.6.10](classes.md#15610-extension-methods). A *fixed_parameter* with a *default_argument* is known as an ***optional parameter***, whereas a *fixed_parameter* without a *default_argument* is a ***required parameter***. A required parameter shall not appear after an optional parameter in a *parameter_list*.
2311+
A *fixed_parameter* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)); an optional `this` modifier; an optional `scoped` modifier; an optional `in`, `out`, `ref` modifier, or `ref readonly`; a *type*; an *identifier*; and an optional *default_argument*. Each *fixed_parameter* declares a parameter of the given type with the given name. The `this` modifier designates the method as an extension method and is only allowed on the first parameter of a static method in a non-generic, non-nested static class. If the parameter is a `struct` type or a type parameter constrained to a `struct`, the `this` modifier may be combined with the `ref`, `ref readonly`, or `in` modifier, but not the `out` modifier. Extension methods are further described in [§15.6.10](classes.md#15610-extension-methods). A *fixed_parameter* with a *default_argument* is known as an ***optional parameter***, whereas a *fixed_parameter* without a *default_argument* is a ***required parameter***. A required parameter shall not appear after an optional parameter in a *parameter_list*.
23122312

23132313
An output parameter implicitly has the `scoped` modifier.
23142314

23152315
For a discussion of `scoped`, see [§9.7.3](variables.md#973-the-scoped-modifier).
23162316

2317-
A parameter with a `ref`, `out` or `this` modifier cannot have a *default_argument*. An input parameter may have a *default_argument*. The *expression* in a *default_argument* shall be one of the following:
2317+
A parameter with a `ref`, `out` or `this` modifier cannot have a *default_argument*. A parameter with an `ref readonly` or `in` modifier may have a *default_argument*; however, in the `ref readonly` case, a warning shall be issued. The *expression* in a *default_argument* shall be one of the following:
23182318

23192319
- a *constant_expression*
23202320
- an expression of the form `new S()` where `S` is a value type
@@ -2358,9 +2358,10 @@ The following kinds of parameters exist:
23582358
- Input parameters ([§15.6.2.3.2](classes.md#156232-input-parameters)).
23592359
- Output parameters ([§15.6.2.3.4](classes.md#156234-output-parameters)).
23602360
- Reference parameters ([§15.6.2.3.3](classes.md#156233-reference-parameters)).
2361+
- Reference readonly parameters, which are reference parameters that also have the `readonly` modifier.
23612362
- Parameter arrays ([§15.6.2.4](classes.md#15624-parameter-arrays)).
23622363
2363-
> *Note*: As described in7.6](basic-concepts.md#76-signatures-and-overloading), the `in`, `out`, and `ref` modifiers are part of a methods signature, but the `params` and `scoped` modifiers are not. *end note*
2364+
> *Note*: As described in7.6](basic-concepts.md#76-signatures-and-overloading), the `in`, `out`, `ref`, and `ref readonly` modifiers are part of a methods signature, but the `params` and `scoped` modifiers are not. *end note*
23642365
23652366
#### 15.6.2.2 Value parameters
23662367
@@ -2380,11 +2381,11 @@ Input, output, and reference parameters are ***by-reference parameter***s. A by-
23802381
23812382
> *Note*: The referent of a by-reference parameter can be changed using the ref assignment (`= ref`) operator.
23822383
2383-
When a parameter is a by-reference parameter, the corresponding argument in a method invocation shall consist of the corresponding keyword, `in`, `ref`, or `out`, followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)) of the same type as the parameter. However, when the parameter is an `in` parameter, the argument may be an *expression* for which an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from that argument expression to the type of the corresponding parameter.
2384+
When a parameter is a by-reference parameter, the corresponding argument in a method invocation shall consist of the corresponding keyword, `in`, `ref`, or `out`, followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)) of the same type as the parameter. However, when the parameter is a `ref readonly` or `in` parameter, the argument may be an *expression* for which an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from that argument expression to the type of the corresponding parameter.
23842385
23852386
By-reference parameters are not allowed on functions declared as an iterator ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)) or async function ([§15.14](classes.md#1514-async-functions)).
23862387
2387-
In a method that takes multiple by-reference parameters, it is possible for multiple names to represent the same storage location.
2388+
In a method that has multiple by-reference parameters, it is possible for multiple parameter names to represent the same storage location.
23882389
23892390
##### 15.6.2.3.2 Input parameters
23902391
@@ -2396,7 +2397,11 @@ It is a compile-time error to modify the value of an input parameter.
23962397
23972398
##### 15.6.2.3.3 Reference parameters
23982399
2399-
A parameter declared with a `ref` modifier is a ***reference parameter***. For definite-assignment rules, see [§9.2.6](variables.md#926-reference-parameters).
2400+
A parameter declared with a `ref` or `ref readonly` modifier is a ***reference parameter***. For definite-assignment rules, see [§9.2.6](variables.md#926-reference-parameters).
2401+
2402+
It is a compile-time error to modify the value of a `ref readonly` parameter.
2403+
2404+
The argument corresponding to a `ref readonly` parameter may be a value, in which case, a variable having that value is created by the implementation ([§12.6.2.3](expressions.md#12623-run-time-evaluation-of-argument-lists)) in the method invocation.
24002405
24012406
> *Example*: The example
24022407
>
@@ -2456,6 +2461,20 @@ A parameter declared with a `ref` modifier is a ***reference parameter***. For d
24562461
> the invocation of `F` in `G` passes a reference to `s` for both `a` and `b`. Thus, for that invocation, the names `s`, `a`, and `b` all refer to the same storage location, and the three assignments all modify the instance field `s`.
24572462
>
24582463
> *end example*
2464+
<!-- markdownlint-disable MD028 -->
2465+
2466+
<!-- markdownlint-enable MD028 -->
2467+
> *Example*: The following example
2468+
>
2469+
> <!-- Example: {template:"standalone-console-without-using", name:"ReferenceParameters2"} -->
2470+
> ```csharp
2471+
> LargeStruct ls /* init somehow */;
2472+
> M(ref ls);
2473+
> static void M(ref readonly LargeStruct p) { /* ... */ }
2474+
> struct LargeStruct { /* ... */ }
2475+
> ```
2476+
>
2477+
> shows a large struct being passed by reference for efficiency, but without the called method having the ability to modify that that struct. *end example*
24592478
24602479
For a `struct` type, within an instance method, instance accessor ([§12.2.1](expressions.md#1221-general)), or instance constructor with a constructor initializer, the `this` keyword behaves exactly as a reference parameter of the struct type ([§12.8.14](expressions.md#12814-this-access)).
24612480

0 commit comments

Comments
 (0)