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
4 changes: 3 additions & 1 deletion standard/classes.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# 15 Classes

Check warning on line 2 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L2

MDC032::Line length 83 > maximum 81
## 15.1 General

Check warning on line 3 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3

MDC032::Line length 88 > maximum 81

A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby a ***derived class*** can extend and specialize a ***base class***.

Check warning on line 6 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6

MDC032::Line length 83 > maximum 81
Structs ([§16](structs.md#16-structs)) and interfaces ([§19](interfaces.md#19-interfaces)) have members similar to classes but with certain restrictions. This clause defines the declarations for classes and class members. The clauses for structs and interfaces define the restrictions for those types in terms of the corresponding declarations in class types.

## 15.2 Class declarations

Check warning on line 9 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L9

MDC032::Line length 97 > maximum 81

Check warning on line 10 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L10

MDC032::Line length 83 > maximum 81
### 15.2.1 General

Check warning on line 12 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L12

MDC032::Line length 87 > maximum 81
A *class_declaration* is a *type_declaration* ([§14.8](namespaces.md#148-type-declarations)) that declares a new class.

```ANTLR
class_declaration

Check warning on line 16 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L16

MDC032::Line length 86 > maximum 81
: non_record_class_declaration
| record_class_declaration

Check warning on line 18 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L18

MDC032::Line length 84 > maximum 81
;

Check warning on line 20 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L20

MDC032::Line length 82 > maximum 81
non_record_class_declaration

Check warning on line 21 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L21

MDC032::Line length 93 > maximum 81
: non_record_class_without_positional_members
| non_record_class_with_positional_members
;
Expand All @@ -27,7 +27,7 @@
: attributes? class_modifier* 'partial'? 'class' identifier
type_parameter_list? class_base?
type_parameter_constraints_clause* class_body
;

Check warning on line 30 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L30

MDC032::Line length 115 > maximum 81

non_record_class_with_positional_members
: attributes? class_modifier* 'partial'? 'class' identifier
Expand All @@ -37,11 +37,11 @@
```

There are two kinds of class: ***non-record class***, as declared by *non_record_class_declaration*, and ***record class***, as declared by *record_class_declaration*. A non-record class is the kind of class that C# has supported since the language’s inception. Record classes were added much later and are discussed in [§15.16](classes.md#1516-record-classes). The differences between the two kinds are discussed in [§15.18](classes.md#1518-record-class-and-non-record-class-differences).

Check warning on line 40 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L40

MDC032::Line length 86 > maximum 81
A *non_record_class_declaration* can have one of two almost identical forms: *non_record_class_without_positional_members* and *non_record_class_with_positional_members*.

A *non_record_class_without_positional_members* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), followed by an optional set of *class_modifier*s ([§15.2.2](classes.md#1522-class-modifiers)), followed by an optional `partial` modifier ([§15.2.7](classes.md#1527-partial-type-declarations)), followed by the keyword `class` and an *identifier* that names the class, followed by an optional *type_parameter_list* ([§15.2.3](classes.md#1523-type-parameters)), followed by an optional *class_base* specification ([§15.2.4](classes.md#1524-class-base-specification)), followed by an optional set of *type_parameter_constraints_clause*s ([§15.2.5](classes.md#1525-type-parameter-constraints)), followed by a *class_body* ([§15.2.6](classes.md#1526-class-body)).

Check warning on line 44 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L44

MDC032::Line length 86 > maximum 81
A *non_record_class_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see [§15.11.6](classes.md#15116-primary-constructors).

A class having a required member ([§15.7.1](classes.md#1571-general)) directly (that is, not through inheritance) shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)).
Expand Down Expand Up @@ -6028,6 +6028,8 @@

It is a compile-time error for the parameter list of an async function to specify any `in`, `out`, or `ref` parameters, or any parameter of a `ref struct` type.

It is a compile-time error for an unsafe context to contain an `await` expression or a `yield return` statement.

The *return_type* of an async method shall be either `void`, a ***task type***, or an ***asynchronous iterator type*** ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). For an async method that produces a result value, a task type or an asynchronous iterator type ([§15.15.3](classes.md#15153-enumerable-interfaces)) shall be generic. For an async method that does not produce a result value, a task type shall not be generic. Such types are referred to in this specification as `«TaskType»<T>` and `«TaskType»`, respectively. The Standard library type `System.Threading.Tasks.Task` and types constructed from `System.Threading.Tasks.Task<TResult>` and `System.Threading.Tasks.ValueTask<T>` are task types, as well as a class, struct or interface type that is associated with a ***task builder type*** via the attribute `System.Runtime.CompilerServices.AsyncMethodBuilderAttribute`. Such types are referred to in this specification as `«TaskBuilderType»<T>` and `«TaskBuilderType»`. A task type can have at most one type parameter and cannot be nested in a generic type.

An async method returning a task type is said to be ***task-returning***.
Expand Down Expand Up @@ -6207,7 +6209,7 @@

An iterator block may occur as a *method_body*, *operator_body* or *accessor_body*, whereas events, instance constructors, static constructors and finalizer shall not be implemented as synchronous or asynchronous iterators.

When a function is implemented using an iterator block, it is a compile-time error for the parameter list of the function to specify any `in`, `out`, or `ref` parameters, or a parameter of a `ref struct` type.
When a function is implemented using an iterator block, it is a compile-time error for the parameter list of the function to specify any `in`, `out`, or `ref` parameters, or a parameter of a `ref struct` type, or a pointer type.

An asynchronous iterator shall support cancellation of the asynchronous operation. This is described in [§23.5.10](attributes.md#23510-the-enumeratorcancellation-attribute).

Expand Down
9 changes: 5 additions & 4 deletions standard/statements.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# 13 Statements

## 13.1 General

Check warning on line 3 in standard/statements.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/statements.md#L3

MDC032::Line length 90 > maximum 81

C# provides a variety of statements.

Check warning on line 6 in standard/statements.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/statements.md#L6

MDC032::Line length 98 > maximum 81
> *Note*: Most of these statements will be familiar to developers who have programmed in C and C++. *end note*

```ANTLR
Expand Down Expand Up @@ -162,10 +162,11 @@

The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.

A *block* that contains one or more `yield` statements ([§13.15](statements.md#1315-the-yield-statement)) is called an iterator block. Iterator blocks are used to implement function members as iterators ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). Some additional restrictions apply to iterator blocks:
A *block* that contains one or more `yield` statements ([§13.15](statements.md#1315-the-yield-statement)) is called an iterator block, even if those `yield` statements are contained only indirectly in nested blocks (excluding nested lambdas and local functions). Iterator blocks are used to implement function members as iterators ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)).

- It is a compile-time error for a `return` statement to appear in an iterator block (but `yield return` statements are permitted).
- It is a compile-time error for an iterator block to contain an unsafe context ([§24.2](unsafe-code.md#242-unsafe-contexts)). An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.
It is a compile-time error for a `return` statement to appear in an iterator block (but `yield return` statements are permitted).

The iterator block used to implement an iterator ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)) always defines a safe context, even when the iterator declaration is nested in an unsafe context.

### 13.3.2 Statement lists

Expand Down Expand Up @@ -477,7 +478,7 @@

If *ref_kind* is `ref readonly`, the *identifier*s being declared are references to variables that are treated as read-only. Otherwise, if *ref_kind* is `ref`, the *identifier*s being declared are references to variables that shall be writable.

It is a compile-time error to declare a ref local variable, or a variable of a `ref struct` type, within a method declared with the *method_modifier* `async`, or within an iterator ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)).
It is a compile-time error to declare and use (even implicitly in compiler-synthesized code) a ref local variable, or a variable of a `ref struct` type across `await` expressions or `yield return` statements. More precisely, the error is driven by the following mechanism: after an `await` expression or a `yield return` statement, all ref local variables and variables of a `ref struct` type in scope are considered definitely unassigned.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that means it is permissible to read a ref local variable in unreachable code.

using System.Collections.Generic;

public class C {
    public IEnumerator<int> M() {
        int i = 0;
        ref int r = ref i;

        yield return r; // OK
        // r is definitely unassigned, because of the yield return above.

        // yield return r; // error

        yield break;
        // r is again definitely assigned, because this point is unreachable.

        yield return r; // OK
    }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear to me that this disallows the following:

using System.Threading.Tasks;

public class C {
    public static async Task M(Task<int> t) {
        int i = 0;
        ref int r = ref i;
        K1(ref r, await t); // error
    }
    
    private static void K1(ref int r, int i) {}
}

One could claim that ref r is evaluated before the await expression and r is still definitely assigned at that point. So this depends on the "compiler-synthesized code" for await expressions but I'm not sure that is specified rigorously enough to say whether the above is allowed.


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

Expand Down
2 changes: 2 additions & 0 deletions standard/unsafe-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,8 @@ An implicit conversion exists from a *unary_expression* whose target is a method
- The selected method `M` shall be compatible (as defined above) with the function pointer type `F`. Otherwise, a compile-time error occurs.
- The result of the conversion is a function pointer of type `F`.

In an iterator, it is a compile-time error to take the address of a local or a parameter.

### 24.6.6 Pointer increment and decrement

In an unsafe context, the `++` and `--` operators ([§12.8.16](expressions.md#12816-postfix-increment-and-decrement-operators) and [§12.9.7](expressions.md#1297-prefix-increment-and-decrement-operators)) can be applied to data pointer variables of all types. It is a compile-time error for these operators to be applied to variables of type *funcptr_type* or *voidptr_type*. Thus, for every data pointer type `T*`, the following operators are implicitly defined:
Expand Down
Loading