Skip to content

Commit 9e0a0f2

Browse files
RexJaeschkeBillWagner
authored andcommitted
Add support for extending partial methods
fix md formatting revert to previous text handle imp/exp private allow partial with ref_kind returns change link's target name
1 parent 1477dfc commit 9e0a0f2

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

standard/classes.md

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,7 +2073,7 @@ ref_kind
20732073
;
20742074
20752075
ref_method_modifiers
2076-
: ref_method_modifier*
2076+
: ref_method_modifier* 'partial'?
20772077
;
20782078
20792079
method_header
@@ -2150,15 +2150,16 @@ A declaration has a valid combination of modifiers if all of the following are t
21502150
- The declaration may include the `abstract` and `override` modifiers so that an abstract member may override a virtual member.
21512151
- If the declaration includes the `private` modifier, then the declaration does not include any of the following modifiers: `virtual`, `override`, or `abstract`.
21522152
- If the declaration includes the `sealed` modifier, then the declaration also includes the `override` modifier.
2153-
- If the declaration includes the `partial` modifier, then it does not include any of the following modifiers: `new`, `public`, `protected`, `internal`, `private`, `virtual`, `sealed`, `override`, `abstract`, or `extern`.
2153+
- If the declaration includes the `partial` modifier, then it does not include the modifier `abstract`.
2154+
- If the declaration is for a restricted partial method ([§15.6.9](classes.md#1569-partial-methods)), then it does not include any of the following modifiers: `new`, `public`, `protected`, `internal`, `private`, `virtual`, `sealed`, `override`, or `extern`.
21542155

21552156
Methods are classified according to what, if anything, they return:
21562157

21572158
- If `ref` is present, the method is ***returns-by-ref*** and returns a *variable reference*, that is optionally read-only;
21582159
- Otherwise, if *return_type* is `void`, the method is ***returns-no-value*** and does not return a value;
21592160
- Otherwise, the method is ***returns-by-value*** and returns a value.
21602161

2161-
The *return_type* of a returns-by-value or returns-no-value method declaration specifies the type of the result, if any, returned by the method. Only a returns-no-value method may include the `partial` modifier ([§15.6.9](classes.md#1569-partial-methods)). If the declaration includes the `async` modifier then *return_type* shall be `void` or the method returns-by-value and the return type is a *task type* ([§15.14.1](classes.md#15141-general)).
2162+
The *return_type* of a returns-by-value or returns-no-value method declaration specifies the type of the result, if any, returned by the method. Only a returns-no-value method may include the `partial` modifier ([§15.6.9](classes.md#1569-partial-methods)). If the declaration includes the `async` modifier then *return_type* for a restricted partial method shall be `void` or the method returns-by-value and the return type is a *task type* ([§15.14.1](classes.md#15141-general)).
21622163

21632164
The *ref_return_type* of a returns-by-ref method declaration specifies the type of the variable referenced by the *variable_reference* returned by the method.
21642165

@@ -2387,7 +2388,7 @@ For a `struct` type, within an instance method, instance accessor ([§12.2.1](ex
23872388
23882389
A parameter declared with an `out` modifier is an ***output parameter***. For definite-assignment rules, see [§9.2.7](variables.md#927-output-parameters).
23892390
2390-
A method declared as a partial method ([§15.6.9](classes.md#1569-partial-methods)) shall not have output parameters.
2391+
A method declared as a restricted partial method ([§15.6.9](classes.md#1569-partial-methods)) shall not have output parameters.
23912392
23922393
> *Note*: Output parameters are typically used in methods that produce multiple return values. *end note*
23932394
<!-- markdownlint-disable MD028 -->
@@ -3025,22 +3026,52 @@ The mechanism by which linkage to an external method is achieved is implementati
30253026
30263027
### 15.6.9 Partial methods
30273028
3028-
When a method declaration includes a `partial` modifier, that method is said to be a ***partial method***. Partial methods may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)), and are subject to a number of restrictions.
3029+
When a *method declaration* includes a `partial` modifier, that method is said to be a ***partial method***. Partial methods may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)).
30293030
3030-
Partial methods may be defined in one part of a type declaration and implemented in another. The implementation is optional; if no part implements the partial method, the partial method declaration and all calls to it are removed from the type declaration resulting from the combination of the parts.
3031+
Partial methods may be defined in one part of a type declaration and implemented in another, or be defined and implemented in the same part.
30313032
3032-
Partial methods shall not define access modifiers; they are implicitly private. Their return type shall be `void`, and their parameters shall not be output parameters. The identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) in a method declaration only if it appears immediately before the `void` keyword. A partial method cannot explicitly implement interface methods.
3033+
There are two kinds of partial method declarations: If the body of the method declaration is a semicolon, the declaration is said to be a ***defining partial method declaration***. Otherwise, the declaration is said to be an ***implementing partial method declaration***. Across the parts of a type declaration, there may be only one defining partial method declaration with a given signature, and there may be only one implementing partial method declaration with a given signature. If an implementing partial method declaration is given, a corresponding defining partial method declaration shall exist, and the declarations shall match as specified in the following:
30333034
3034-
There are two kinds of partial method declarations: If the body of the method declaration is a semicolon, the declaration is said to be a ***defining partial method declaration***. If the body is other than a semicolon, the declaration is said to be an ***implementing partial method declaration***. Across the parts of a type declaration, there shall be only one defining partial method declaration with a given signature, and there shall be at most only one implementing partial method declaration with a given signature. If an implementing partial method declaration is given, a corresponding defining partial method declaration shall exist, and the declarations shall match as specified in the following:
3035-
3036-
- The declarations shall have the same modifiers (although not necessarily in the same order), method name, number of type parameters and number of parameters.
3037-
- Corresponding parameters in the declarations shall have the same modifiers (although not necessarily in the same order) and the same types, or identity convertible types (modulo differences in type parameter names).
3035+
- The declarations shall have the same modifiers (although not necessarily in the same order), method name, number of type parameters, and number of parameters. In the case of private accessibility, both shall be implicitly private (that is, with no accessibility modifier) or both shall be explicitly `private`.
3036+
- Corresponding parameters in the declarations shall have the same modifiers (although not necessarily in the same order) and the same types (modulo differences in type parameter names).
30383037
- Corresponding type parameters in the declarations shall have the same constraints (modulo differences in type parameter names).
30393038
3040-
An implementing partial method declaration can appear in the same part as the corresponding defining partial method declaration.
3039+
Over time, the specification for partial methods has evolved, resulting in restricted and unrestricted versions. A ***restricted partial method*** has no explicit access modifiers (and is implicitly private), has a `void` return type, and has no out parameters. An ***unrestricted partial method*** is a partial method that has explicit access modifiers, a non-`void` return type, or any out parameters.
3040+
3041+
For a restricted partial method, the implementation is optional; if no part implements the partial method, the partial method declaration and all calls to it are removed from the type declaration resulting from the combination of the parts. For an unrestricted partial method both the definition and implementation shall exist.
3042+
3043+
In *method_declaration*, the identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) only if it immediately precedes the *return_type*. A partial method cannot explicitly implement interface methods.
3044+
3045+
> *Example*:
3046+
>
3047+
> <!-- Example: {template:"standalone-lib-without-using", name:"PartialMethods2", replaceEllipsis:true, customEllipsisReplacements: ["", "return true;", "i = 10;"]} -->
3048+
> ```csharp
3049+
> // part containing defining partial method declarations
3050+
> partial class C
3051+
> {
3052+
> partial void M1(); // restricted, impl. optional
3053+
> private partial void M2(); // unrestricted, impl. required
3054+
> protected partial bool M3(); // unrestricted, impl. required
3055+
> public partial void M4(out int i); // unrestricted, impl. required
3056+
> }
3057+
>
3058+
> // part containing implementing partial method declarations
3059+
> partial class C
3060+
> {
3061+
> private partial void M2() { ... }
3062+
> protected partial bool M3() { ... }
3063+
> public partial void M4(out int i) { ... }
3064+
> }
3065+
> ```
3066+
>
3067+
> *end example*
3068+
3069+
Only a defining partial method participates in overload resolution. As such, in the case of a restricted partial method, whether or not an implementing declaration is given, invocation expressions may resolve to invocations of the partial method.
30413070
3042-
Only a defining partial method participates in overload resolution. Thus, whether or not an implementing declaration is given, invocation expressions may resolve to invocations of the partial method. Because a partial method always returns `void`, such invocation expressions will always be expression statements. Furthermore, because a partial method is implicitly `private`, such statements will always occur within one of the parts of the type declaration within which the partial method is declared.
3071+
> *Note*: Because a restricted partial method always returns `void`, such invocation expressions will always be expression statements. Furthermore, because a restricted partial method is implicitly `private`, such statements will always occur within one of the parts of the type declaration within which the partial method is declared. *end note*
3072+
<!-- markdownlint-disable MD028 -->
30433073
3074+
<!-- markdownlint-enable MD028 -->
30443075
> *Note*: The definition of matching defining and implementing partial method declarations does not require parameter names to match. This can produce *surprising*, albeit *well defined*, behaviour when named arguments ([§12.6.2.1](expressions.md#12621-general)) are used. For example, given the defining partial method declaration for `M` in one file, and the implementing partial method declaration in another file:
30453076
>
30463077
> <!-- Example: {template:"standalone-lib-without-using", name:"PartialMethods1", "expectedErrors":["CS1739"], "expectedWarnings":["CS8826"]} -->
@@ -3063,7 +3094,7 @@ Only a defining partial method participates in overload resolution. Thus, whethe
30633094
>
30643095
> *end note*
30653096
3066-
If no part of a partial type declaration contains an implementing declaration for a given partial method, any expression statement invoking it is simply removed from the combined type declaration. Thus the invocation expression, including any subexpressions, has no effect at run-time. The partial method itself is also removed and will not be a member of the combined type declaration.
3097+
If a restricted partial method has no implementation, any expression statement invoking it is simply removed from the combined type declaration. Thus, the invocation expression, including any subexpressions, has no effect at run-time. The partial method itself is also removed and will not be a member of the combined type declaration.
30673098
30683099
If an implementing declaration exists for a given partial method, the invocations of the partial methods are retained. The partial method gives rise to a method declaration similar to the implementing partial method declaration except for the following:
30693100
@@ -3073,7 +3104,7 @@ If an implementing declaration exists for a given partial method, the invocation
30733104
30743105
- The attributes on the parameters of the resulting method declaration are the combined attributes of the corresponding parameters of the defining and the implementing partial method declaration in unspecified order. Duplicates are not removed.
30753106
3076-
If a defining declaration but not an implementing declaration is given for a partial method `M`, the following restrictions apply:
3107+
If a defining declaration but not an implementing declaration is given for a restricted partial method `M`, the following restrictions apply:
30773108
30783109
- It is a compile-time error to create a delegate from `M` ([§12.8.17.5](expressions.md#128175-delegate-creation-expressions)).
30793110

0 commit comments

Comments
 (0)