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
43 changes: 41 additions & 2 deletions 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***.

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 11 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L11

MDC032::Line length 83 > maximum 81

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 @@ -453,6 +453,11 @@
;

type_parameter_constraints
: restrictive_type_parameter_constraints (',' anti_constraints_clause)?
| anti_constraints_clause
;

restrictive_type_parameter_constraints
: primary_constraint (',' secondary_constraints)? (',' constructor_constraint)?
| secondary_constraints (',' constructor_constraint)?
| constructor_constraint
Expand All @@ -479,11 +484,25 @@
constructor_constraint
: 'new' '(' ')'
;

anti_constraints_clause
: 'allows' anti_constraints

anti_constraints
: anti_constraint (',' anti_constraint)*

anti_constraint
: ref_struct_clause

ref_struct_clause
: 'ref' 'struct'
```

Each *type_parameter_constraints_clause* consists of the token `where`, followed by the name of a type parameter, followed by a colon and the list of constraints for that type parameter. There can be at most one `where` clause for each type parameter, and the `where` clauses can be listed in any order. Like the `get` and `set` tokens in a property accessor, the `where` token is not a keyword.
Each *type_parameter_constraints_clause* consists of the token `where`, followed by the name of a type parameter, followed by a colon and the list of constraints and anti-constraints (see definition below) for that type parameter. There can be at most one `where` clause for each type parameter, and the `where` clauses can be listed in any order. Like the `get` and `set` tokens in a property accessor, the `where` token is not a keyword.

The list of constraints given in a `where` clause can include any of the following components, in this order: a single primary constraint, one or more secondary constraints, and the constructor constraint, `new()`.
The list of constraints and anti-constraints given in a `where` clause can include any of the following components, in this order: a *primary_constraint*, one or more *secondary_constraint*s, a *constructor_constraint*, and an *anti_constraints_clause*.

> *Note*: Although the grammar permits *anti_constraints* to contain multiple *anti_constraint*s, this is for future expansion, and in this edition of this specification the only anti-constraint is `ref struct`. *end note*

A primary constraint can be a class type, the ***reference type constraint*** `class`, the ***value type constraint*** `struct`, the ***not null constraint*** `notnull`, the ***unmanaged type constraint*** `unmanaged`, or `default`. The class type and the reference type constraint can include the *nullable_type_annotation*.

Expand Down Expand Up @@ -644,6 +663,26 @@

It is a compile-time error for *type_parameter_constraints* having a *primary_constraint* of `struct` or `unmanaged` to also have a *constructor_constraint*.

Ordinarily, a ref struct type cannot be used as a type argument for a generic type or method. However, the presence of an *anti_constraints_clause* containing `allows ref struct` permits such a use. This clause is referred to as an ***anti-constraint***, as it expands the set of allowed type arguments rather than limits them like all other constraints.
When a type parameter has this anti-constraint, ref safety rules on all instances of that type parameter shall be enforced.

The anti-constraint is not inherited from a type parameter type constraint. In the code below, `S` cannot be substituted with a ref struct:

```csharp
class C<T, S>
where T : allows ref struct
where S : T
{}
```

Given `where T : allows ref struct`, `T` shall not

- Also be constrained to a known reference type
- Also be constrained with `class` or `class?`
- Be used as a generic argument unless the corresponding parameter also has the anti-constraint

It is a compile-time error to invoke a non-virtual instance method (or property) on a type parameter with `allows ref struct`.

> *Example*: The following are examples of constraints:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"TypeParameterConstraints1", replaceEllipsis:true} -->
Expand Down
2 changes: 1 addition & 1 deletion standard/lexical-structure.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 6 Lexical structure

Check warning on line 2 in standard/lexical-structure.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/lexical-structure.md#L2

MDC032::Line length 84 > maximum 81
## 6.1 Programs

A C# ***program*** consists of one or more source files, each known formally as a ***compilation unit*** ([§14.2](namespaces.md#142-compilation-units)). Although a compilation unit might have a one-to-one correspondence with a file in a file system, such correspondence is not required.
Expand All @@ -7,7 +7,7 @@
Conceptually speaking, a program is compiled using three steps:

1. Transformation, which converts a file from a particular character repertoire and encoding scheme into a sequence of Unicode characters.
1. Lexical analysis, which translates a stream of Unicode input characters into a stream of tokens.

Check warning on line 10 in standard/lexical-structure.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/lexical-structure.md#L10

MDC032::Line length 85 > maximum 81
1. Syntactic analysis, which translates the stream of tokens into executable code.

Apart from accepting UTF-8 encoded input (as required by [§5](conformance.md#5-conformance), a conforming implementation may choose to accept and transform additional character encoding schemes (such as UTF-16, UTF-32, or non-Unicode character mappings).
Expand Down Expand Up @@ -605,7 +605,7 @@

```ANTLR
contextual_keyword
: 'add' | 'alias' | 'and' | 'ascending' | 'async'
: 'add' | 'alias' | 'allows' | 'and' | 'ascending' | 'async'
| 'await' | 'by' | 'Cdecl' | 'descending'| 'dynamic'
| 'equals' | 'Fastcall' | 'file' | 'from' | 'get'
| 'global' | 'group' | 'init' | 'into' | 'join'
Expand Down
2 changes: 1 addition & 1 deletion standard/standard-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ namespace System
void Dispose();
}

public interface IEquatable<T>
public interface IEquatable<T> where T : allows ref struct
{
bool Equals(T? other);
}
Expand Down
12 changes: 9 additions & 3 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 @@ -2071,9 +2071,15 @@
;
```

A ***resource type*** is either a class or non-ref struct that implements either or both of the `System.IDisposable` or `System.IAsyncDisposable` interfaces, which includes a single parameterless method named `Dispose` and/or `DisposeAsync`; or a ref struct that includes a method named `Dispose` having the same signature as that declared by `System.IDisposable`. Code that is using a resource can call `Dispose` or `DisposeAsync` to indicate that the resource is no longer needed.
A ***resource type*** is either a class or struct that implements either or both of the `System.IDisposable` or `System.IAsyncDisposable` interfaces, which includes a single parameterless method named `Dispose` and/or `DisposeAsync`. A ref struct that includes a method named `Dispose` having the same signature as that declared by `System.IDisposable` is also a resource type. In this case, preference is given to a `Dispose` method that implements the pattern, and only if one is not found, shall `IDisposable` be used.

If the form of *resource_acquisition* is *non_ref_local_variable_declaration* then the type of the *non_ref_local_variable_declaration* shall be either `dynamic` or a resource type. If the form of *resource_acquisition* is *expression* then this expression shall have a resource type. If `await` is present, the resource type shall implement `System.IAsyncDisposable`. A `ref struct` type cannot be the resource type for a `using` statement with the `await` modifier.
A using statement shall recognize and use an implementation of `Idisposable` when the resource is a type parameter has the `ref struct` anti-constraint, and `Idisposable` is in its effective interfaces set.

> *Note*: A pattern `Dispose` method will not be recognized on a type parameter that has the `ref struct` anti-constraint because an interface is not a ref struct. *end note*

Code that is using a resource can call `Dispose` or `DisposeAsync` to indicate that the resource is no longer needed.

If the form of *resource_acquisition* is *non_ref_local_variable_declaration* then the type of the *non_ref_local_variable_declaration* shall be either `dynamic` or a resource type. If the form of *resource_acquisition* is *expression* then this expression shall have a resource type. If `await` is present, the resource type shall implement `System.IAsyncDisposable`.

Local variables declared in a *resource_acquisition* are read-only, and shall include an initializer. A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the `++` and `--` operators), take the address of them, or pass them as reference or output parameters.

Expand All @@ -2085,7 +2091,7 @@
using (ResourceType resource = «expression») «statement»
```

corresponds to one of three possible formulations. For class and non-ref struct resources, when `ResourceType` is a non-nullable value type or a type parameter with the value type constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)), the formulation is semantically equivalent to:
corresponds to one of three possible formulations. For class and struct resources, when `ResourceType` is a non-nullable value type or a type parameter with the value type constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)), the formulation is semantically equivalent to:

```csharp
{
Expand Down
4 changes: 2 additions & 2 deletions standard/structs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 16 Structs

## 16.1 General

Check warning on line 3 in standard/structs.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/structs.md#L3

MDC032::Line length 82 > maximum 81

Structs are similar to classes in that they represent data structures that can contain data members and function members. However, unlike classes, structs are value types and do not require heap allocation. A variable of a `struct` type directly contains the data of the `struct`, whereas a variable of a class type contains a reference to the data, the latter known as an object.

Expand All @@ -12,7 +12,7 @@

### 16.2.1 General

A *struct_declaration* is a *type_declaration* ([§14.8](namespaces.md#148-type-declarations)) that declares a new struct:

Check warning on line 15 in standard/structs.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/structs.md#L15

MDC032::Line length 91 > maximum 81

```ANTLR
struct_declaration
Expand All @@ -22,7 +22,7 @@

non_record_struct_declaration
: non_record_struct_without_positional_members
| non_record_struct_with_positional_members

Check warning on line 25 in standard/structs.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/structs.md#L25

MDC032::Line length 82 > maximum 81
;

non_record_struct_without_positional_members
Expand Down Expand Up @@ -106,7 +106,6 @@

- As the element type of an array.
- As the declared type of a field of a class or a struct that does not have the `ref` modifier.
- As a type argument.
- As the type of a tuple element.
- In an async method.
- In an iterator.
Expand All @@ -116,13 +115,14 @@
In addition, the following restrictions apply to a `ref struct` type:

- A `ref struct` type shall not be boxed to `System.ValueType` or `System.Object`.
- A `ref struct` type shall not be declared to implement any interface.
- An instance method declared in `object` or in `System.ValueType` but not overridden in a `ref struct` type shall not be called with a receiver of that `ref struct` type.

> *Note*: A `ref struct` shall not declare `async` instance methods nor use a `yield return` or `yield break` statement within an instance method, because the implicit `this` parameter cannot be used in those contexts. *end note*

These constraints ensure that a variable of `ref struct` type does not refer to stack memory that is no longer valid, or to variables that are no longer valid.

Although a `ref struct` type may implement an interface, that `ref struct` type shall implement all instance members of that interface, even if they have default implementations.

### 16.2.4 Partial modifier

The `partial` modifier indicates that this *struct_declaration* is a partial type declaration. Multiple partial struct declarations with the same name within an enclosing namespace or type declaration combine to form one struct declaration, following the rules specified in [§15.2.7](classes.md#1527-partial-type-declarations).
Expand Down
Loading