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
2 changes: 0 additions & 2 deletions standard/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@
> ```csharp
> #nullable enable
> public class X
> {

Check warning on line 970 in standard/attributes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/attributes.md#L970

MDC032::Line length 86 > maximum 81
> private void ThrowIfNull([DoesNotReturnIf(true)] bool isNull, string argumentName)
> {
> if (isNull)
Expand Down Expand Up @@ -1192,5 +1192,3 @@
> Now, the indexer’s name is `TheItem`.
>
> *end example*


9 changes: 5 additions & 4 deletions standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@
: 'where' type_parameter ':' type_parameter_constraints
;

type_parameter_constraints

Check warning on line 425 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L425

MDC032::Line length 83 > maximum 81
: primary_constraint (',' secondary_constraints)? (',' constructor_constraint)?
| secondary_constraints (',' constructor_constraint)?
| constructor_constraint
Expand Down Expand Up @@ -534,15 +534,15 @@
> static void M()
> {
> // nonnull constraint allows nonnullable struct type argument
> A<int> x1;

Check warning on line 537 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L537

MDC032::Line length 87 > maximum 81
> // possible warning: nonnull constraint prohibits nullable struct type argument
> A<int?> x2;
> // nonnull constraint allows nonnullable class type argument
> A<C> x3;

Check warning on line 541 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L541

MDC032::Line length 86 > maximum 81
> // possible warning: nonnull constraint prohibits nullable class type argument
> A<C?> x4;

Check warning on line 543 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L543

MDC032::Line length 84 > maximum 81
> // nonnullable base class requirement allows nonnullable class type argument
> B1<C> x5;

Check warning on line 545 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L545

MDC032::Line length 82 > maximum 81
> // possible warning: nonnullable base class requirement prohibits nullable
> // class type argument
> B1<C?> x6;
Expand Down Expand Up @@ -3556,7 +3556,7 @@
> static void Main()
> {
> field = 10;
> Console.WriteLine(Property); // Prints 10

Check warning on line 3559 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3559

MDC032::Line length 83 > maximum 81
> Property = 20; // This invokes the get accessor, then assigns
> // via the resulting variable reference
> Console.WriteLine(field); // Prints 20
Expand Down Expand Up @@ -4917,7 +4917,7 @@
: '!'
;

overloadable_unary_operator

Check warning on line 4920 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L4920

MDC032::Line length 82 > maximum 81
: '+' | '-' | logical_negation_operator | '~' | '++' | '--' | 'true' | 'false'
;

Expand Down Expand Up @@ -5272,7 +5272,11 @@

### 15.11.3 Instance variable initializers

When a non-extern instance constructor has no constructor initializer, or it has a constructor initializer of the form `base(...)`, that constructor implicitly performs the initializations specified by the *variable_initializer*s of the instance fields declared in its class. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. The variable initializers are executed in the textual order in which they appear in the class declaration ([§15.5.6](classes.md#1556-variable-initializers)).
When a non-extern class instance constructor has no constructor initializer, or it has a constructor initializer of the form `base(...)`, that constructor implicitly performs the initializations specified by the *variable_initializer*s of the instance fields declared in its class. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. The variable initializers are executed in the textual order in which they appear in the class declaration ([§15.5.6](classes.md#1556-variable-initializers)).

When a struct instance constructor has no constructor initializer, that constructor implicitly performs the initializations specified by the *variable_initializer*s of the instance fields declared in its struct. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor.

When a struct instance constructor has a `this()` constructor initializer that represents the *default parameterless constructor*, the declared constructor implicitly clears all instance fields and performs the initializations specified by the *variable_initializer*s of the instance fields declared in its struct. Immediately upon entry to the constructor, all value type fields are set to their default value and all reference type fields are set to `null`. Immediately after that, a sequence of assignments corresponding to the *variable_initializer*s are executed.

Variable initializers are not required to be executed by extern instance constructors.

Expand Down Expand Up @@ -6134,7 +6138,7 @@
> public static bool operator!=(R1? left, R1? right) => !(left == right);
>
> public override int GetHashCode()
> {

Check warning on line 6141 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6141

MDC032::Line length 93 > maximum 81
> return HashCode.Combine(EqualityComparer<Type>.Default.GetHashCode(EqualityContract),
> EqualityComparer<T1>.Default.GetHashCode(P1));
> }
Expand Down Expand Up @@ -6315,7 +6319,7 @@
> protected virtual bool PrintMembers(StringBuilder builder)
> {
> builder.Append(nameof(P1));
> builder.Append(" = ");

Check warning on line 6322 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6322

MDC032::Line length 97 > maximum 81
> builder.Append(this.P1); // or builder.Append(this.P1.ToString()); if P1 has a value type
> return true;
> }
Expand Down Expand Up @@ -6346,11 +6350,11 @@
> builder.Append(", ");
> }
> builder.Append(nameof(P2));
> builder.Append(" = ");

Check warning on line 6353 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6353

MDC032::Line length 86 > maximum 81
> builder.Append(this.P2); // or builder.Append(this.P2); if P2 has a value type
> builder.Append(", ");
> builder.Append(nameof(P3));
> builder.Append(" = ");

Check warning on line 6357 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6357

MDC032::Line length 86 > maximum 81
> builder.Append(this.P3); // or builder.Append(this.P3); if P3 has a value type
> return true;
> }
Expand Down Expand Up @@ -6483,6 +6487,3 @@
> ```
>
> *end example*



3 changes: 2 additions & 1 deletion standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2238,8 +2238,8 @@
A *null_conditional_invocation_expression* is syntactically either a *null_conditional_member_access* ([§12.8.8](expressions.md#1288-null-conditional-member-access)) or *null_conditional_element_access* ([§12.8.13](expressions.md#12813-null-conditional-element-access)) where the final *dependent_access* is an invocation expression ([§12.8.10](expressions.md#12810-invocation-expressions)).

A *null_conditional_invocation_expression* occurs within the context of a *statement_expression* ([§13.7](statements.md#137-expression-statements)), *anonymous_function_body* ([§12.22.1](expressions.md#12221-general)), or *method_body* ([§15.6.1](classes.md#1561-general)).

Check warning on line 2241 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2241

MDC032::Line length 84 > maximum 81
Unlike the syntactically equivalent *null_conditional_member_access* or *null_conditional_element_access*, a *null_conditional_invocation_expression* may be classified as nothing.

Check warning on line 2242 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2242

MDC032::Line length 85 > maximum 81

```ANTLR
null_conditional_invocation_expression
Expand Down Expand Up @@ -2319,7 +2319,7 @@
- The *primary_expression* has compile-time type `dynamic`.
- At least one expression of the *argument_list* has compile-time type `dynamic`.

In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation).

Check warning on line 2322 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2322

MDC032::Line length 82 > maximum 81

> *Example*:
>
Expand Down Expand Up @@ -2635,7 +2635,8 @@
The binding-time processing of an *object_creation_expression* of the form `new T(A)`, where the specified or implied type `T` is a *class_type*, or a *value_type*, and `A` is an optional *argument_list*, consists of the following steps:

- If `T` is a *value_type* and `A` is not present:
- The *object_creation_expression* is a default constructor invocation. The result of the *object_creation_expression* is a value of type `T`, namely the default value for `T` as defined in [§8.3.3](types.md#833-default-constructors).
- If `T` is a *struct_type* that has an explicitly declared parameterless instance constructor, that constructor is a candidate and is selected via overload resolution as described below.
- Otherwise, the *object_creation_expression* is a default constructor invocation. The result of the *object_creation_expression* is a value of type `T`, namely the default value for `T` as defined in [§8.3.3](types.md#833-default-constructors).
- Otherwise, if `T` is a *type_parameter* and `A` is not present:
- If no value type constraint or constructor constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)) has been specified for `T`, a binding-time error occurs.
- The result of the *object_creation_expression* is a value of the run-time type that the type parameter has been bound to, namely the result of invoking the default constructor of that type. The run-time type may be a reference type or a value type.
Expand Down Expand Up @@ -3464,7 +3465,7 @@
- one of the following value types: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `nint`, `nuint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool`; or
- any enumeration type.

### 12.8.22 Stack allocation

Check warning on line 3468 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3468

MDC032::Line length 86 > maximum 81

A stack allocation expression allocates a block of memory from the execution stack. The ***execution stack*** is an area of memory where local variables are stored. The execution stack is not part of the managed heap. The memory used for local variable storage is automatically recovered when the current function returns.

Expand Down Expand Up @@ -3932,8 +3933,8 @@
All non-positional properties being changed shall have both set and init accessors.

This expression is evaluated as follows:

Check warning on line 3936 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3936

MDC032::Line length 84 > maximum 81
- The receiver's clone method ([§15.16.3](classes.md#15163-copy-and-clone-members)) is invoked, and its result is converted to the receiver’s type.

Check warning on line 3937 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3937

MDC032::Line length 85 > maximum 81
- Each `member_initializer` is processed the same way as an assignment to
a field or property access of the result of the conversion. Assignments are processed in lexical order. If *member_initializer_list* is omitted, no members are changed.

Expand Down Expand Up @@ -5374,11 +5375,11 @@
- Otherwise, `y` is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.

## 12.22 Anonymous function expressions

Check warning on line 5378 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5378

MDC032::Line length 92 > maximum 81
### 12.22.1 General

An ***anonymous function*** is an expression that represents an “in-line” method definition. An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression-tree type. The evaluation of an anonymous-function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method that the anonymous function defines. If it is an expression-tree type, the conversion evaluates to an expression tree that represents the structure of the method as an object structure.

Check warning on line 5382 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5382

MDC032::Line length 90 > maximum 81
> *Note*: For historical reasons, there are two syntactic flavors of anonymous functions, namely *lambda_expression*s and *anonymous_method_expression*s. For almost all purposes, *lambda_expression*s are more concise and expressive than *anonymous_method_expression*s, which remain in the language for backwards compatibility. *end note*

```ANTLR
Expand Down
62 changes: 45 additions & 17 deletions standard/structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
> public readonly void AddMessage(string message)
> {
> if (messages == null)
> {

Check warning on line 173 in standard/structs.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/structs.md#L173

MDC032::Line length 91 > maximum 81
> throw new InvalidOperationException("Messages collection is not initialized.");
> }
> messages.Add(message);
Expand All @@ -192,8 +192,6 @@
- The default value of a struct is the value produced by setting all fields to their default value ([§16.4.5](structs.md#1645-default-values)).
- Boxing and unboxing operations are used to convert between a struct type and certain reference types ([§16.4.6](structs.md#1646-boxing-and-unboxing)).
- The meaning of `this` is different within struct members ([§16.4.7](structs.md#1647-meaning-of-this)).
- Instance field declarations for a struct are not permitted to include variable initializers ([§16.4.8](structs.md#1648-field-initializers)).
- A struct is not permitted to declare a parameterless instance constructor ([§16.4.9](structs.md#1649-constructors)).
- A struct is not permitted to declare a finalizer.
- Event declarations, property declarations, property accessors, indexer declarations, and method declarations are permitted to have the modifier `readonly` while that is not generally permitted for those same member kinds in classes.

Expand Down Expand Up @@ -297,7 +295,7 @@
>
> *end example*

The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). Unlike a class, a struct is not permitted to declare a parameterless instance constructor. Instead, every struct implicitly has a parameterless instance constructor, which always returns the value that results from setting all fields to their default values.
The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). When a struct does not declare an explicit parameterless instance constructor, the default constructor is synthesized and always returns the value that results from setting all fields to their default values. The `default` expression always produces the zero-initialized default value, even when a struct declares an explicit parameterless instance constructor ([§16.4.9](structs.md#1649-constructors)).

> *Note*: Structs should be designed to consider the default initialization state a valid state. In the example
>
Expand Down Expand Up @@ -427,64 +425,94 @@

### 16.4.8 Field initializers

As described in [§16.4.5](structs.md#1645-default-values), the default value of a struct consists of the value that results from setting all value type fields to their default value and all reference type fields to `null`. For this reason, a struct does not permit instance field declarations to include variable initializers. This restriction applies only to instance fields. Static fields of a struct are permitted to include variable initializers.
As described in [§16.4.5](structs.md#1645-default-values), the default value of a struct consists of the value that results from setting all value type fields to their default value and all reference type fields to `null`. Static and instance fields of a struct are permitted to include variable initializers; however, in the case of an instance field initializer, at least one instance constructor shall also be declared, or for a record struct, a *delimited_parameter_list* shall be present.

> *Example*: The following
> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"FieldInitializers", expectedErrors:["CS8983"], ignoredWarnings:["CS0649"]} -->
> <!-- Example: {template:"standalone-console", name:"FieldInitializers", inferOutput:true} -->
> ```csharp
> Console.WriteLine($"Point is {new Point()}");
>
> struct Point
> {
> public int x = 1; // Error, initializer not permitted
> public int y = 1; // Error, initializer not permitted
> public int x = 1;
> public int y = 1;
>
> public Point() { }
>
> public override string ToString()
> {
> return "(" + x + ", " + y + ")";
> }
> }
> ```
>
> is in error because the instance field declarations include variable initializers.
> ```console
> Point is (1, 1)
> ```
>
> *end example*

When a struct instance constructor has no constructor initializer, that constructor implicitly performs the initializations specified by the *variable_initializer*s of the instance fields declared in its struct. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor.

When a struct instance constructor has a `this()` constructor initializer that represents the default parameterless constructor, the declared constructor implicitly clears all instance fields and performs the initializations specified by the *variable_initializer*s of the instance fields declared in its struct. Immediately upon entry to the constructor, all value type fields are set to their default value and all reference type fields are set to `null`. Immediately after that, a sequence of assignments corresponding to the *variable_initializer*s are executed.

A *field_declaration* declared directly inside a *struct_declaration* having the *struct_modifier* `readonly` shall have the *field_modifier* `readonly`.

### 16.4.9 Constructors

Unlike a class, a struct is not permitted to declare a parameterless instance constructor. Instead, every struct implicitly has a parameterless instance constructor, which always returns the value that results from setting all value type fields to their default value and all reference type fields to `null` ([§8.3.3](types.md#833-default-constructors)). A struct can declare instance constructors having parameters.
A struct can declare instance constructors, with zero or more parameters. If a struct has no explicitly declared parameterless instance constructor, one is synthesized, with public accessibility, which always returns the value that results from setting all value type fields to their default value and all reference type fields to `null` ([§8.3.3](types.md#833-default-constructors)). In such a case, any instance field initializers are ignored when that constructor executes.

> *Example*: Given the following
An explicitly declared parameterless instance constructor shall have public accessibility.

> *Example*: Given the following:
>
> <!-- Example: {template:"standalone-console-without-using", name:"Constructors1", ignoredWarnings:["CS0219"]} -->
> <!-- Example: {template:"standalone-console", name:"Constructors1", ignoredWarnings:["CS0219"], inferOutput:true} -->
> ```csharp
> using System;
> struct Point
> {
> int x, y;
> int x = -1, y = -2;
>
> public Point(int x, int y)
> {
> this.x = x;
> this.y = y;
> }
>
> public override string ToString()
> {
> return "(" + x + ", " + y + ")";
> }
> }
>
> class A
> {
> static void Main()
> {
> Point p1 = new Point();
> Point p2 = new Point(0, 0);
> Console.WriteLine($"Point is {new Point()}");
> Console.WriteLine($"Point is {new Point(0,0)}");
> }
> }
> ```
>
> the statements both create a `Point` with `x` and `y` initialized to zero.
> ```console
> Point is (0, 0)
> Point is (0, 0)
> ```
>
> the statements both create a `Point` with `x` and `y` initialized to zero, which in the case of the call to the parameterless instance constructor, may be surprising, as both instance fields have initializers, but they are *not* executed.
>
> *end example*

A struct instance constructor is not permitted to include a constructor initializer of the form `base(`*argument_list*`)`, where *argument_list* is optional.
A struct instance constructor is not permitted to include a constructor initializer of the form `base(`*argument_list*`)`, where *argument_list* is optional. The execution of an instance constructor shall not result in the execution of a constructor in the struct’s base type `System.ValueType`.

The `this` parameter of a struct instance constructor corresponds to an output parameter of the struct type. As such, `this` shall be definitely assigned ([§9.4](variables.md#94-definite-assignment)) at every location where the constructor returns. Similarly, it cannot be read (even implicitly) in the constructor body before being definitely assigned.

If the struct instance constructor specifies a constructor initializer, that initializer is considered a definite assignment to this that occurs prior to the body of the constructor. Therefore, the body itself has no initialization requirements.

Instance fields (other than `fixed` fields) shall be definitely assigned in struct instance constructors that do not have a `this()` initializer.

> *Example*: Consider the instance constructor implementation below:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"Constructors2", expectedErrors:["CS0188"]} -->
Expand Down
6 changes: 3 additions & 3 deletions standard/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@

### 8.3.3 Default constructors

All value types implicitly declare a public parameterless instance constructor called the ***default constructor***. The default constructor returns a zero-initialized instance known as the ***default value*** for the value type:
All value types have a public parameterless instance constructor called the ***default constructor***. For struct types that do not explicitly declare a parameterless instance constructor, the default constructor is synthesized by the compiler. The default constructor returns a zero-initialized instance known as the ***default value*** for the value type:

- For all *simple_type*s, the default value is the value produced by a bit pattern of all zeros:
- For `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `nint`, `nuint`, `long`, and `ulong`, the default value is `0`.
Expand All @@ -244,7 +244,7 @@

Like any other instance constructor, the default constructor of a value type is invoked using the `new` operator.

> *Note*: For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. For value types, the default value expression ([§12.8.21](expressions.md#12821-default-value-expressions)) produces the same result as using the default constructor. *end note*
> *Note*: For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. For value types that do not have an explicitly declared parameterless instance constructor, the default value expression ([§12.8.21](expressions.md#12821-default-value-expressions)) produces the same result as using the default constructor. For struct types that declare an explicit parameterless instance constructor, `default` produces the zero-initialized default value, while `new S()` invokes the declared constructor, and the results may differ. *end note*
<!-- markdownlint-disable MD028 -->

<!-- markdownlint-enable MD028 -->
Expand All @@ -265,7 +265,7 @@
>
> *end example*

Because every value type implicitly has a public parameterless instance constructor, it is not possible for a struct type to contain an explicit declaration of a parameterless constructor. A struct type is however permitted to declare parameterized instance constructors ([§16.4.9](structs.md#1649-constructors)).
A struct type is permitted to declare instance constructors, including a parameterless instance constructor. An explicitly declared parameterless instance constructor shall have public accessibility ([§16.4.9](structs.md#1649-constructors)).

### 8.3.4 Struct types

Expand Down Expand Up @@ -1078,8 +1078,8 @@
> {
> var t = new Test();
> if (t.DisappearingProperty != null)
> {

Check warning on line 1081 in standard/types.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/types.md#L1081

MDC032::Line length 82 > maximum 81
> int len = t.DisappearingProperty.Length; // No warning. A compiler can

Check warning on line 1082 in standard/types.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/types.md#L1082

MDC032::Line length 83 > maximum 81
> // assume property is stateful
> }
> }
Expand Down
Loading