From f8d024ba21ef146cee182cdf6a515ee66ce208ff Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:24:34 -0500 Subject: [PATCH 01/13] support required members --- standard/lexical-structure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 1f3a89cba..10b002022 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -629,7 +629,7 @@ contextual_keyword | 'group' | 'init' | 'into' | 'join' | 'let' | 'managed' | 'nameof' | 'nint' | 'not' | 'notnull' | 'nuint' | 'on' | 'or' | 'orderby' | 'partial' - | 'record' | 'remove' | 'select' | 'set' | 'Stdcall' + | 'record' | 'remove' | 'required' | 'select' | 'set' | 'Stdcall' | 'Thiscall' | 'unmanaged' | 'value' | 'var' | 'when' | 'where' | 'yield' ; From 6fb9c41569fc71d2a79090686ec0db96cfd312f5 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:30:59 -0500 Subject: [PATCH 02/13] support required members --- standard/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/types.md b/standard/types.md index b4bd2f20d..3184802e6 100644 --- a/standard/types.md +++ b/standard/types.md @@ -640,7 +640,7 @@ Whenever a constructed type or generic method is referenced, the supplied type a - `A` is a `struct` type or `enum` type, but not a nullable value type. > *Note*: `System.ValueType` and `System.Enum` are reference types that do not satisfy this constraint. *end note* - `A` is a type parameter having the value type constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)). -- If the constraint is the constructor constraint `new()`, the type `A` shall not be `abstract` and shall have a public parameterless constructor. This is satisfied if one of the following is true: +- If the constraint is the constructor constraint `new()`, the type `A` shall not be `abstract`, it shall not have a required member list ([§15.7.1](classes.md#1571-general)), and it shall have a public parameterless constructor. This is satisfied if one of the following is true: - `A` is a value type, since all value types have a public default constructor ([§8.3.3](types.md#833-default-constructors)). - `A` is a type parameter having the constructor constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)). - `A` is a type parameter having the value type constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)). From 5c9b7834ddadb369345749f2398d7cacdea8734e Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:33:31 -0500 Subject: [PATCH 03/13] support required members --- standard/expressions.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/standard/expressions.md b/standard/expressions.md index 82ce81a03..65153a42f 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -3518,6 +3518,25 @@ A *default_value_expression* is a constant expression ([§12.26](expressions.md# - 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. +When an instance of a struct `S` having a required member list ([§15.7.1](classes.md#1571-general)) is created with a value of `default` or `default(S)`, required-member setting is not enforced. However, such setting is enforced for an instance created with `new S()`, even when `S` has no parameterless constructor and the default struct constructor is used. + +> *Example*: Consider the following: +> +> +> ```csharp +> S v1 = default; // OK: no checking for required members +> S v2 = default(S); // OK: no checking for required members +> S v3 = new S(); // error: required member must be set +> S v4 = new S() { reqInt = default }; // OK: required member is set +> +> public struct S +> { +> public required int reqInt; +> } +> ``` +> +> *end example* + ### 12.8.22 Stack allocation 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. From 8b313b5554f1ef2596878e125c0129c50f02525e Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:45:31 -0500 Subject: [PATCH 04/13] support required members --- standard/classes.md | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 594d56fb5..a9f93e1b2 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -27,6 +27,8 @@ class_tag A *class_declaration* 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 a *class_tag* 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 *delimited_parameter_list* ([§15.6.2.1](classes.md#15621-general)), 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)), optionally followed by a semicolon. +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` (§RequiredMember). + A class declaration shall not supply *type_parameter_constraints_clause*s unless it also supplies a *type_parameter_list*. A class declaration that supplies a *type_parameter_list* is a generic class declaration. Additionally, any class nested inside a generic class declaration or a generic struct declaration is itself a generic class declaration, since type arguments for the containing type shall be supplied to create a constructed type ([§8.4](types.md#84-constructed-types)). @@ -1070,7 +1072,7 @@ The inherited members of a constructed class type are the members of the immedia ### 15.3.5 The new modifier -A *class_member_declaration* is permitted to declare a member with the same name or signature as an inherited member. When this occurs, the derived class member is said to *hide* the base class member. See [§7.7.2.3](basic-concepts.md#7723-hiding-through-inheritance) for a precise specification of when a member hides an inherited member. +A *class_member_declaration* is permitted to declare a member with the same name or signature as an inherited member. When this occurs, the derived class member is said to *hide* the base class member. However, it is an error to hide a required member ([§15.7.1](classes.md#1571-general)). See [§7.7.2.3](basic-concepts.md#7723-hiding-through-inheritance) for a precise specification of when a member hides an inherited member. An inherited member `M` is considered to be ***available*** if `M` is accessible and there is no other inherited accessible member N that already hides `M`. Implicitly hiding an inherited member is not considered an error, but a compiler shall issue a warning unless the declaration of the derived class member includes a `new` modifier to explicitly indicate that the derived member is intended to hide the base member. If one or more parts of a partial declaration ([§15.2.7](classes.md#1527-partial-type-declarations)) of a nested type include the `new` modifier, no warning is issued if the nested type hides an available inherited member. @@ -1691,6 +1693,7 @@ field_modifier | 'static' | 'readonly' | 'volatile' + | 'required' | unsafe_modifier // unsafe code support ; @@ -1705,7 +1708,7 @@ variable_declarator *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -A *field_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), and a `static` modifier ([§15.5.2](classes.md#1552-static-and-instance-fields)). In addition, a *field_declaration* may include a `readonly` modifier ([§15.5.3](classes.md#1553-readonly-fields)) or a `volatile` modifier ([§15.5.4](classes.md#1554-volatile-fields)), but not both. The attributes and modifiers apply to all of the members declared by the *field_declaration*. It is an error for the same modifier to appear multiple times in a *field_declaration*. +A *field_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), and a `static` modifier ([§15.5.2](classes.md#1552-static-and-instance-fields)). In addition, a *field_declaration* may include a `readonly` modifier ([§15.5.3](classes.md#1553-readonly-fields)) or a `volatile` modifier ([§15.5.4](classes.md#1554-volatile-fields)), but not both. A *field_declaration* may also include a `required` modifier ([§15.7.1](classes.md#1571-general)), provided it does not have a `readonly` modifier. The attributes and modifiers apply to all of the members declared by the *field_declaration*. It is an error for the same modifier to appear multiple times in a *field_declaration*. The *type* of a *field_declaration* specifies the type of the members introduced by the declaration. The type is followed by a list of *variable_declarator*s, each of which introduces a new member. A *variable_declarator* consists of an *identifier* that names that member, optionally followed by an “`=`” token and a *variable_initializer* ([§15.5.6](classes.md#1556-variable-initializers)) that gives the initial value of that member. @@ -3401,6 +3404,7 @@ property_modifier | 'abstract' | 'extern' | 'readonly' // struct members only + | 'required' | unsafe_modifier // unsafe code support ; @@ -3448,6 +3452,24 @@ In a *ref_property_body* an expression body consisting of `=>` followed by `ref` When a property declaration includes an `extern` modifier, the property is said to be an ***external property***. Because an external property declaration provides no actual implementation, each of the *accessor_body*s in its *accessor_declarations* shall be a semicolon. +The modifier `required` indicates the instance member being declared is required to be set during object initialization, which forces the instance creator to provide an initial value for the member in an object initializer at the creation site. (See [§12.8.20](expressions.md#12820-default-value-expressions) and §SetsRequiredMembersAttribute for exemptions to this requirement.) A required member shall not be static. A required member shall be at least as accessible as its containing type. + +> *Note*: Although a required member declaration may include an initializer (*property_initializer* for a property, *variable_initializer* for a field), ordinarily, that initializer serves no purpose, as the instance creator is required to provide an initial value for that member anyway. However, if a constructor is decorated with the `SetsRequiredMembers` attribute the compiler assumes that member has been initialized correctly, and will not require an explicit initializer by the instance creator, resulting in the member’s initial value being that of its initializer, if one is present. *end note* + +A ***required member list*** is a list of all the members of a type that are required. A type automatically inherits this list from its base type. +To build the required member list `R` for a type `T`, the following steps are used: + +1. For every type `Tb`, starting with `T` and working through the base type chain until `object` is reached. +1. If `Tb` is decorated with the `RequiredMember` attribute (§RequiredMember), then all members of `Tb` marked with that attribute are gathered into `Rb` + 1. For every `Ri` in `Rb`, if `Ri` is overridden by any member of `R`, it is skipped. + 1. Otherwise, if any `Ri` is hidden by a member of `R`, then the lookup of required members fails, and no further steps are taken. Calling any constructor of `T` not decorated with the `SetsRequiredMembers` is an error. + 1. Otherwise, `Ri` is added to `R`. + +A required member shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` (§RequiredMember). +With regard to nullable reference type analysis ([§8.9](types.md#8.9-types-and-nullability)), a required member need not be initialized to a valid nullable state when any of its instance constructors returns. Any required member in a type and its base types is considered by nullable analysis to have its default value at the beginning of any instance constructor in that type, unless it chains to a `this` or `base` constructor that is decorated with the `SetsRequiredMembersAttribute` attribute. + +Nullable analysis shall warn about all required members from the current and base types that do not have a valid nullable state at the end of a constructor decorated with the `SetsRequiredMembersAttribute` attribute. + ### 15.7.2 Static and instance properties When a property declaration includes a `static` modifier, the property is said to be a ***static property***. When no `static` modifier is present, the property is said to be an ***instance property***. @@ -4242,6 +4264,8 @@ An accessor that is used to implement an interface shall not have an *accessor_m > > *end example* +The set or init accessor of a required property ([§15.7.1](classes.md#1571-general)) shall be at least as accessible as that property’s containing type. + ### 15.7.6 Virtual, sealed, override, and abstract accessors *Note*: This subclause applies to both properties ([§15.7](classes.md#157-properties)) and indexers ([§15.9](classes.md#159-indexers)). The subclause is written in terms of properties, when reading for indexers substitute indexer/indexers for property/properties and consult the list of differences between properties and indexers given in [§15.9.2](classes.md#1592-indexer-and-property-differences). *end note* @@ -4250,6 +4274,10 @@ A virtual property declaration specifies that the accessors of the property are An abstract property declaration specifies that the accessors of the property are virtual, but does not provide an actual implementation of the accessors. Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the property. Because an accessor for an abstract property declaration provides no actual implementation, its *accessor_body* simply consists of a semicolon. An abstract property shall not have a `private` accessor. +A property that overrides a base property that is required ([§15.7.1](classes.md#1571-general)) shall itself be required. A property that overrides a base property that is not required may itself be required, in which case, the derived type member is added to that type’s required member list. + +> *Note*: A type is permitted to override a required virtual property. This means that if the base virtual property has storage, and the derived type tries to access the base implementation of that property, it could observe uninitialized storage. *end note* + A property declaration that includes both the `abstract` and `override` modifiers specifies that the property is abstract and overrides a base property. The accessors of such a property are also abstract. Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§19.4.4](interfaces.md#1944-interface-properties)). The accessors of an inherited virtual property can be overridden in a derived class by including a property declaration that specifies an `override` directive. This is known as an ***overriding property declaration***. An overriding property declaration does not declare a new property. Instead, it simply specializes the implementations of the accessors of an existing virtual property. @@ -5215,6 +5243,15 @@ Each of the types referenced in the *parameter_list* of an instance constructor The optional *constructor_initializer* specifies another instance constructor to invoke before executing the statements given in the *constructor_body* of this instance constructor. This is described further in [§15.11.2](classes.md#15112-constructor-initializers). +All instance constructors on a type that has a required member list ([§15.7.1](classes.md#1571-general)) automatically advertise a contract that consumers of the type shall initialize all of the properties in the list. It is an error for an instance constructor to advertise a contract that requires a member that is not at least as accessible as the constructor itself. +An instance constructor whose *constructor_initializer* chains to another constructor decorated with the `SetsRequiredMembers` attribute (§SetsRequiredMembers), shall also be decorated with that attribute. +For every instance constructor `Ci` in type `T` with required members `R`, unless `Ci` is decorated with the attribute `SetsRequiredMembers`consumers, calling `Ci` shall involve one of the following: + +- Set all members of `R` in an *object_initializer* on the *object_creation_expression*, +- Or set all members of `R` via the *named_argument_list* of an *attribute*. + +If the current context does not permit an *object_initializer* or is not an *attribute* with *named_argument_list*, and `Ci` is not decorated with `SetsRequiredMembers`, then it is an error to call `Ci`. + When a constructor declaration includes an `extern` modifier, the constructor is said to be an ***external constructor***. Because an external constructor declaration provides no actual implementation, its *constructor_body* consists of a semicolon. For all other constructors, the *constructor_body* consists of either - a *block*, which specifies the statements to initialize a new instance of the class; or @@ -5485,6 +5522,8 @@ A ***copy constructor*** for a type `T` is a constructor having a single paramet In certain circumstances ([§15.16.3](classes.md#15163-copy-and-clone-members)), a copy constructor may be synthesized by the compiler, and called by synthesized code. +A copy constructor on a type that has a required member list ([§15.7.1](classes.md#1571-general)) shall be decorated with the `SetsRequiredMembers` attribute (§SetsRequiredMembers). + ## 15.12 Static constructors A ***static constructor*** is a member that implements the actions required to initialize a closed class. Static constructors are declared using *static_constructor_declaration*s: From 40f367151801a5ecab517798299ac6a72a5b5a24 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:50:39 -0500 Subject: [PATCH 05/13] support required members --- standard/interfaces.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/standard/interfaces.md b/standard/interfaces.md index 666042de0..798404516 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -299,7 +299,7 @@ This clause augments the description of fields in classes [§15.5](classes.md#15 Interface fields are declared using *field_declaration*s ([§15.5.1](classes.md#1551-general)) with the following additional rules: -- It is a compile-time error for *field_declaration* to declare an instance field. +- It is a compile-time error for *field_declaration* to declare an instance field. (As such, an interface field cannot be marked `required`.) > *Example*: The following program contains static members of various kinds: > @@ -443,6 +443,8 @@ Interface properties are declared using *property_declaration*s ([§15.7.1](clas - An interface method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. - An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). +It is a compile-time error for an interface property to be marked `required`. + ### 19.4.5 Interface events This clause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces. @@ -949,6 +951,8 @@ The qualified interface member name of an explicit interface member implementati > > *end example* +It is a compile-time error for an explicit interface implementation of a member to have the modifier `required`. + ### 19.6.3 Uniqueness of implemented interfaces The interfaces implemented by a generic type declaration shall remain unique for all possible constructed types. Without this rule, it would be impossible to determine the correct method to call for certain constructed types. From 03e3249f2353259972d8a038f4b82d3349037e28 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 10:58:42 -0500 Subject: [PATCH 06/13] support required members --- standard/attributes.md | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/standard/attributes.md b/standard/attributes.md index b5d043fb2..5693e34f8 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -498,6 +498,7 @@ A number of attributes affect the language in some way. These attributes include - `System.Runtime.CompilerServices.EnumeratorCancellationAttribute` ([§23.5.8](attributes.md#2358-the-enumeratorcancellation-attribute)), which is used to specify parameter for the cancellation token in an asynchronous iterator. - `System.Runtime.CompilerServices.ModuleInitializer` ([§23.5.9](attributes.md#2359-the-moduleinitializer-attribute)), which is used to mark a method as a module initializer. - `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` and `System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute`, which are used to declare a custom interpolated string expression handler ([§23.5.9.1](attributes.md#23591-custom-interpolated-string-expression-handlers)) and to call one of its constructors, respectively. +- `System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute` (§SetsRequiredMembers) and `System.Runtime.CompilerServices.RequiredMemberAttribute` (§RequiredMember), which are used in required-member contexts ([§15.7.1](classes.md#1571-general)). The Nullable static analysis attributes ([§23.5.7](attributes.md#2357-code-analysis-attributes)) can improve the correctness of warnings generated for nullabilities and null states ([§8.9.5](types.md#895-nullabilities-and-null-states)). @@ -1428,6 +1429,65 @@ Attribute `InterpolatedStringHandlerArgument` is applied to the handler paramete If an `out bool` parameter is also declared to allow the handler to be inhibited ([§23.5.9.1.2](attributes.md#235912-inhibiting-a-custom-handler)) that parameter shall be the final one. +### §Required-Member-Attributes Required member attributes + +#### §SetsRequiredMembers The SetsRequiredMembers attribute + +This attribute indicates that the constructor it decorates sets all required members for the current type, so callers do not need to set any required members themselves. However, the compiler doesn't verify that the constructor actually initializes all required members. + +> *Example*: +> +> +> ```csharp +> public class Person +> { +> public Person() { } +> +> [SetsRequiredMembers] +> public Person(string firstName, string lastName) => +> (FirstName, LastName) = (firstName, lastName); +> +> public required string FirstName { get; init; } +> public required string LastName { get; init; } +> +> public int? Age { get; set; } +> } +> +> public class Student : Person +> { +> public Student() : base() +> { +> } +> +> [SetsRequiredMembers] +> public Student(string firstName, string lastName) : +> base(firstName, lastName) +> { +> } +> +> public double GPA { get; set; } +> } +> +> public class Test +> { +> public static void M() +> { +> var p1 = new Student(); // error: doesn't set required members +> var p2 = new Student("Jane", "Williams"); // OK +> } +> } +> ``` +> +> *end example* + + + +> *Note*: As the derived-type constructor `Student(string, string)` chains to the base-type constructor `Person(string, string)`, which has this attribute, the derived-type constructor must also have that attribute ([§15.11.1](classes.md#15111-general)). *end note* + +#### §RequiredMember The RequiredMember attribute + +This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute. + ## 23.6 Attributes for interoperation For interoperation with other languages, an indexer may be implemented using indexed properties. If no `IndexerName` attribute is present for an indexer, then the name `Item` is used by default. The `IndexerName` attribute enables a developer to override this default and specify a different name. From f76ea39347fcff1a65fa7dee224232cc62cd765a Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 11:04:22 -0500 Subject: [PATCH 07/13] support required members --- standard/standard-library.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/standard/standard-library.md b/standard/standard-library.md index 153bffed1..14371f7ba 100644 --- a/standard/standard-library.md +++ b/standard/standard-library.md @@ -772,6 +772,13 @@ namespace System.Diagnostics.CodeAnalysis { public NotNullWhenAttribute(bool returnValue); } + + [System.AttributeUsage(System.AttributeTargets.Constructor, + AllowMultiple=false, Inherited=false)] + public sealed class SetsRequiredMembersAttribute : Attribute + { + public SetsRequiredMembersAttribute() {} + } } namespace System.Linq.Expressions @@ -887,6 +894,14 @@ namespace System.Runtime.CompilerServices public ModuleInitializerAttribute() { } } + [System.AttributeUsage(System.AttributeTargets.Class | + System.AttributeTargets.Field | System.AttributeTargets.Property | + System.AttributeTargets.Struct, AllowMultiple=false, Inherited=false)] + public sealed class RequiredMemberAttribute : Attribute + { + public RequiredMemberAttribute() {} + } + public readonly struct TaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion { @@ -1438,6 +1453,7 @@ The following library types are referenced in this specification. The full names - `global::System.Diagnostics.CodeAnalysis.NotNullAttribute` - `global::System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute` - `global::System.Diagnostics.CodeAnalysis.NotNullWhenAttribute` +- `global::System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute` - `global::System.Linq.Expressions.Expression` - `global::System.Reflection.MemberInfo` - `global::System.Runtime.CompilerServices.AsyncMethodBuilderAttribute` @@ -1453,6 +1469,7 @@ The following library types are referenced in this specification. The full names - `global::System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute` - `global::System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` - `global::System.Runtime.CompilerServices.ModuleInitializerAttribute` +- `global::System.Runtime.CompilerServices.RequiredMemberAttribute` - `global::System.Runtime.CompilerServices.TaskAwaiter` - `global::System.Runtime.CompilerServices.TaskAwaiter` - `global::System.Runtime.CompilerServices.ValueTaskAwaiter` From 9ba4e3b1d1ef9dfa143cb935d5a4b7c6fbb27ea5 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 11:16:45 -0500 Subject: [PATCH 08/13] fix md formatting --- standard/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/attributes.md b/standard/attributes.md index 5693e34f8..2c01393a5 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -1486,7 +1486,7 @@ This attribute indicates that the constructor it decorates sets all required mem #### §RequiredMember The RequiredMember attribute -This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute. +This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute. ## 23.6 Attributes for interoperation From 09e788cca219fda565d31e2d8202a27f6e1155ac Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 11:18:40 -0500 Subject: [PATCH 09/13] fix md formatting --- standard/classes.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index a9f93e1b2..6e9914a4a 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3461,9 +3461,10 @@ To build the required member list `R` for a type `T`, the following steps are us 1. For every type `Tb`, starting with `T` and working through the base type chain until `object` is reached. 1. If `Tb` is decorated with the `RequiredMember` attribute (§RequiredMember), then all members of `Tb` marked with that attribute are gathered into `Rb` - 1. For every `Ri` in `Rb`, if `Ri` is overridden by any member of `R`, it is skipped. - 1. Otherwise, if any `Ri` is hidden by a member of `R`, then the lookup of required members fails, and no further steps are taken. Calling any constructor of `T` not decorated with the `SetsRequiredMembers` is an error. - 1. Otherwise, `Ri` is added to `R`. + + - For every `Ri` in `Rb`, if `Ri` is overridden by any member of `R`, it is skipped. + - Otherwise, if any `Ri` is hidden by a member of `R`, then the lookup of required members fails, and no further steps are taken. Calling any constructor of `T` not decorated with the `SetsRequiredMembers` is an error. + - Otherwise, `Ri` is added to `R`. A required member shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` (§RequiredMember). With regard to nullable reference type analysis ([§8.9](types.md#8.9-types-and-nullability)), a required member need not be initialized to a valid nullable state when any of its instance constructors returns. Any required member in a type and its base types is considered by nullable analysis to have its default value at the beginning of any instance constructor in that type, unless it chains to a `this` or `base` constructor that is decorated with the `SetsRequiredMembersAttribute` attribute. From a39a73d1831bd9e889732bc69f3d41bc7f4269f7 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 11:19:40 -0500 Subject: [PATCH 10/13] fix md formatting --- standard/interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/interfaces.md b/standard/interfaces.md index 798404516..6faf237bf 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -299,7 +299,7 @@ This clause augments the description of fields in classes [§15.5](classes.md#15 Interface fields are declared using *field_declaration*s ([§15.5.1](classes.md#1551-general)) with the following additional rules: -- It is a compile-time error for *field_declaration* to declare an instance field. (As such, an interface field cannot be marked `required`.) +- It is a compile-time error for *field_declaration* to declare an instance field. (As such, an interface field cannot be marked `required`.) > *Example*: The following program contains static members of various kinds: > From ede694a6c28d164592a0b6334f8e62af0a7d2647 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 11:23:58 -0500 Subject: [PATCH 11/13] fix md formatting --- standard/classes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 6e9914a4a..ec088e76b 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3462,9 +3462,9 @@ To build the required member list `R` for a type `T`, the following steps are us 1. For every type `Tb`, starting with `T` and working through the base type chain until `object` is reached. 1. If `Tb` is decorated with the `RequiredMember` attribute (§RequiredMember), then all members of `Tb` marked with that attribute are gathered into `Rb` - - For every `Ri` in `Rb`, if `Ri` is overridden by any member of `R`, it is skipped. - - Otherwise, if any `Ri` is hidden by a member of `R`, then the lookup of required members fails, and no further steps are taken. Calling any constructor of `T` not decorated with the `SetsRequiredMembers` is an error. - - Otherwise, `Ri` is added to `R`. + 1. For every `Ri` in `Rb`, if `Ri` is overridden by any member of `R`, it is skipped. + 1. Otherwise, if any `Ri` is hidden by a member of `R`, then the lookup of required members fails, and no further steps are taken. Calling any constructor of `T` not decorated with the `SetsRequiredMembers` is an error. + 1. Otherwise, `Ri` is added to `R`. A required member shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` (§RequiredMember). With regard to nullable reference type analysis ([§8.9](types.md#8.9-types-and-nullability)), a required member need not be initialized to a valid nullable state when any of its instance constructors returns. Any required member in a type and its base types is considered by nullable analysis to have its default value at the beginning of any instance constructor in that type, unless it chains to a `this` or `base` constructor that is decorated with the `SetsRequiredMembersAttribute` attribute. From bd25ce42165bed7f0e168d855c552586148f2359 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:00:08 -0500 Subject: [PATCH 12/13] fix section heading ref --- standard/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index ec088e76b..6443d13c3 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3452,7 +3452,7 @@ In a *ref_property_body* an expression body consisting of `=>` followed by `ref` When a property declaration includes an `extern` modifier, the property is said to be an ***external property***. Because an external property declaration provides no actual implementation, each of the *accessor_body*s in its *accessor_declarations* shall be a semicolon. -The modifier `required` indicates the instance member being declared is required to be set during object initialization, which forces the instance creator to provide an initial value for the member in an object initializer at the creation site. (See [§12.8.20](expressions.md#12820-default-value-expressions) and §SetsRequiredMembersAttribute for exemptions to this requirement.) A required member shall not be static. A required member shall be at least as accessible as its containing type. +The modifier `required` indicates the instance member being declared is required to be set during object initialization, which forces the instance creator to provide an initial value for the member in an object initializer at the creation site. (See [§12.8.20](expressions.md#12820-default-value-expressions) and §SetsRequiredMembers for exemptions to this requirement.) A required member shall not be static. A required member shall be at least as accessible as its containing type. > *Note*: Although a required member declaration may include an initializer (*property_initializer* for a property, *variable_initializer* for a field), ordinarily, that initializer serves no purpose, as the instance creator is required to provide an initial value for that member anyway. However, if a constructor is decorated with the `SetsRequiredMembers` attribute the compiler assumes that member has been initialized correctly, and will not require an explicit initializer by the instance creator, resulting in the member’s initial value being that of its initializer, if one is present. *end note* From cc1f70bf01fd11fe078fbc7acfd3279fc8a79d3c Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:04:07 -0500 Subject: [PATCH 13/13] fix links --- standard/classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 6443d13c3..bae0b291e 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3452,7 +3452,7 @@ In a *ref_property_body* an expression body consisting of `=>` followed by `ref` When a property declaration includes an `extern` modifier, the property is said to be an ***external property***. Because an external property declaration provides no actual implementation, each of the *accessor_body*s in its *accessor_declarations* shall be a semicolon. -The modifier `required` indicates the instance member being declared is required to be set during object initialization, which forces the instance creator to provide an initial value for the member in an object initializer at the creation site. (See [§12.8.20](expressions.md#12820-default-value-expressions) and §SetsRequiredMembers for exemptions to this requirement.) A required member shall not be static. A required member shall be at least as accessible as its containing type. +The modifier `required` indicates the instance member being declared is required to be set during object initialization, which forces the instance creator to provide an initial value for the member in an object initializer at the creation site. (See [§12.8.21](expressions.md#12821-default-value-expressions) and §SetsRequiredMembers for exemptions to this requirement.) A required member shall not be static. A required member shall be at least as accessible as its containing type. > *Note*: Although a required member declaration may include an initializer (*property_initializer* for a property, *variable_initializer* for a field), ordinarily, that initializer serves no purpose, as the instance creator is required to provide an initial value for that member anyway. However, if a constructor is decorated with the `SetsRequiredMembers` attribute the compiler assumes that member has been initialized correctly, and will not require an explicit initializer by the instance creator, resulting in the member’s initial value being that of its initializer, if one is present. *end note* @@ -3467,7 +3467,7 @@ To build the required member list `R` for a type `T`, the following steps are us 1. Otherwise, `Ri` is added to `R`. A required member shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` (§RequiredMember). -With regard to nullable reference type analysis ([§8.9](types.md#8.9-types-and-nullability)), a required member need not be initialized to a valid nullable state when any of its instance constructors returns. Any required member in a type and its base types is considered by nullable analysis to have its default value at the beginning of any instance constructor in that type, unless it chains to a `this` or `base` constructor that is decorated with the `SetsRequiredMembersAttribute` attribute. +With regard to nullable reference type analysis ([§8.9](types.md#89-reference-types-and-nullability)), a required member need not be initialized to a valid nullable state when any of its instance constructors returns. Any required member in a type and its base types is considered by nullable analysis to have its default value at the beginning of any instance constructor in that type, unless it chains to a `this` or `base` constructor that is decorated with the `SetsRequiredMembersAttribute` attribute. Nullable analysis shall warn about all required members from the current and base types that do not have a valid nullable state at the end of a constructor decorated with the `SetsRequiredMembersAttribute` attribute.