From 007a3047d3c54fa354cb9a9d5e4d2b8ee023066f Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 07:20:41 -0500 Subject: [PATCH 01/11] Allow interfaces as well --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index d2c0df118..cbd7b7bc5 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -6614,7 +6614,7 @@ A constant expression may be either a value type or a reference type. If a const Only the following constructs are permitted in constant expressions: - Literals (including the `null` literal). -- References to `const` members of class and struct types. +- References to `const` members of class, struct, and interface types. - References to members of enumeration types. - References to local constants. - Parenthesized subexpressions, which are themselves constant expressions. From da2107bd896888f0c97895661c2066f1e072bce7 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 07:52:54 -0500 Subject: [PATCH 02/11] support default interface function members --- standard/classes.md | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 6d81a34ae..7044e9f0b 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -271,7 +271,11 @@ The base classes of a class are the direct base class and its base classes. In o Except for class `object`, every class has exactly one direct base class. The `object` class has no direct base class and is the ultimate base class of all other classes. -It is a compile-time error for a class to depend on itself. For the purpose of this rule, a class ***directly depends on*** its direct base class (if any) and *directly depends on* the nearest enclosing class within which it is nested (if any). Given this definition, the complete set of classes upon which a class depends is the transitive closure of the *directly depends on* relationship. +It is a compile-time error for a class to depend on itself. For the purpose of this rule, a class ***directly depends on*** its direct base class (if any) and *directly depends on* the type within which it is immediately nested (if any). + +When an interface `IB` extends an interface `IA`, it is a compile-time error for `IA` to depend on `IB`. An interface **directly depends on** its direct base interfaces (if any) and **directly depends on** the type within which it is immediately nested (if any). + +Given these definitions, the complete set of types upon which a type depends is the transitive closure of the *directly depends on* relationship. > *Example*: The example > @@ -1384,6 +1388,8 @@ void Finalize(); ## 15.4 Constants +[This subclause covers constant declarations in classes and structs. That text is augmented by information about declaring constants in interfaces (§interface-constants).] + A ***constant*** is a class member that represents a constant value: a value that can be computed at compile-time. A *constant_declaration* introduces one or more constants of a given type. ```ANTLR @@ -1478,6 +1484,8 @@ Constant declarations may depend on constants from other programs, but such depe ### 15.5.1 General +[[§14.5](classes.md#145-fields) and its subclauses cover field declarations in classes. That text is augmented by information about declaring fields in structs ([§15.4.1](structs.md#1541-general)) and interfaces (§interface-fields).] + A ***field*** is a member that represents a variable associated with an object or class. A *field_declaration* introduces one or more fields of a given type. ```ANTLR @@ -1901,6 +1909,8 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General +[[§14.6](classes.md#146-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§15.4](structs.md#154-class-and-struct-differences)) and interfaces ([§17.4.2](interfaces.md#1742-interface-methods)).] + A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: ```ANTLR @@ -2742,9 +2752,9 @@ When an instance method declaration includes a `sealed` modifier, that method is When an instance method declaration includes an `abstract` modifier, that method is said to be an ***abstract method***. Although an abstract method is implicitly also a virtual method, it cannot have the modifier `virtual`. -An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. Because an abstract method provides no actual implementation, the method body of an abstract method simply consists of a semicolon. +An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. (For an abstract interface method, an implementation may also be provided by a derived interface.) Because an abstract method provides no actual implementation, the *method_body* of an abstract method simply consists of a semicolon. -Abstract method declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). +Abstract method declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§18.4.2](interfaces.md#1842-interface-methods)). > *Example*: In the following code > @@ -2766,7 +2776,7 @@ Abstract method declarations are only permitted in abstract classes ([§15.2.2.2 > } > ``` > -> the `Shape` class defines the abstract notion of a geometrical shape object that can paint itself. The `Paint` method is abstract because there is no meaningful default implementation. The `Ellipse` and `Box` classes are concrete `Shape` implementations. Because these classes are non-abstract, they are required to override the `Paint` method and provide an actual implementation. +> the `Shape` class defines the abstract notion of a geometrical shape object that can paint itself. The `Paint` method is abstract because there is no meaningful fallback implementation for the abstract concept of shape. The `Ellipse` and `Box` classes are concrete `Shape` implementations. Because these classes are non-abstract, they are required to override the `Paint` method and provide an actual implementation. > > *end example* @@ -3113,6 +3123,8 @@ For returns-by-value and returns-by-ref methods the endpoint of the method body ### 15.7.1 General +[[§14.7](classes.md#147-properties) and its subclauses cover property declarations in classes. That text is augmented by information about declaring properties in structs ([§15.4](structs.md#154-class-and-struct-differences)) and in interfaces ([§17.4.3](interfaces.md#1743-interface-properties)).] + A ***property*** is a member that provides access to a characteristic of an object or a class. Examples of properties include the length of a string, the size of a font, the caption of a window, the name of a customer, and so on. Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties do not denote storage locations. Instead, properties have ***accessors*** that specify the statements to be executed when their values are read or written. Properties thus provide a mechanism for associating actions with the reading and writing of an object’s characteristics; furthermore, they permit such characteristics to be computed. Properties are declared using *property_declaration*s: @@ -3245,7 +3257,7 @@ For a ref-valued property the *ref_get_accessor_declaration* consists optional a The use of *accessor_modifier*s is governed by the following restrictions: -- An *accessor_modifier* shall not be used in an interface or in an explicit interface member implementation. +- An *accessor_modifier* shall not be used in an explicit interface member implementation. - For a property or indexer that has no `override` modifier, an *accessor_modifier* is permitted only if the property or indexer has both a get and set accessor, and then is permitted only on one of those accessors. - For a property or indexer that includes an `override` modifier, an accessor shall match the *accessor_modifier*, if any, of the accessor being overridden. - The *accessor_modifier* shall declare an accessibility that is strictly more restrictive than the declared accessibility of the property or indexer itself. To be precise: @@ -3753,11 +3765,15 @@ An accessor that is used to implement an interface shall not have an *accessor_m A virtual property declaration specifies that the accessors of the property are virtual. The `virtual` modifier applies to all non-private accessors of a property. When an accessor of a virtual property has the private *accessor_modifier*, the `private` accessor is implicitly not virtual. -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. +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. (For an abstract interface property, an implementation may also be provided by a derived interface.) 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 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. +<<<<<<< HEAD Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). 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. +======= +Abstract property declarations are only permitted in abstract classes ([§14.2.2.2](classes.md#14222-abstract-classes)) and interfaces ([§17.4.3](interfaces.md#1743-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. +>>>>>>> 948e2b0 (support default interface function members) The override declaration and the overridden base property are required to have the same declared accessibility. In other words, an override declaration may not change the accessibility of the base property. However, if the overridden base property is protected internal and it is declared in a different assembly than the assembly containing the override declaration then the override declaration’s declared accessibility shall be protected. If the inherited property has only a single accessor (i.e., if the inherited property is read-only or write-only), the overriding property shall include only that accessor. If the inherited property includes both accessors (i.e., if the inherited property is read-write), the overriding property can include either a single accessor or both accessors. There shall be an identity conversion between the type of the overriding and the inherited property. @@ -3855,6 +3871,8 @@ When a property is declared as an override, any overridden accessors shall be ac ### 15.8.1 General +[[§14.8](classes.md#14-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§17.4.4](interfaces.md#1744-interface-events)).] + An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handlers***. Events are declared using *event_declaration*s: @@ -4119,11 +4137,15 @@ The differences between static and instance members are discussed further in [§ A virtual event declaration specifies that the accessors of that event are virtual. The `virtual` modifier applies to both accessors of an event. -An abstract event declaration specifies that the accessors of the event 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 event. Because an accessor for an abstract event declaration provides no actual implementation, it shall not provide *event_accessor_declaration*s. +An abstract event declaration specifies that the accessors of the event 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 event. (For an abstract interface event, an implementation may also be provided by a derived interface.) Because an accessor for an abstract event declaration provides no actual implementation, it shall not provide *event_accessor_declaration*s. An event declaration that includes both the `abstract` and `override` modifiers specifies that the event is abstract and overrides a base event. The accessors of such an event are also abstract. +<<<<<<< HEAD Abstract event declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). +======= +Abstract event declarations are only permitted in abstract classes ([§14.2.2.2](classes.md#14222-abstract-classes)) and interfaces ([§17.4.4](interfaces.md#1744-interface-events)). +>>>>>>> 948e2b0 (support default interface function members) The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an `override` modifier. This is known as an ***overriding event declaration***. An overriding event declaration does not declare a new event. Instead, it simply specializes the implementations of the accessors of an existing virtual event. @@ -4139,6 +4161,8 @@ Except for differences in declaration and invocation syntax, virtual, sealed, ov ### 15.9.1 General +[This subclause covers indexer declarations in classes. That text is augmented by information about declaring indexers in structs ([§15.4](structs.md#154-class-and-struct-differences)) and in interfaces ([§17.4.5](interfaces.md#1745-interface-indexers)).] + An ***indexer*** is a member that enables an object to be indexed in the same way as an array. Indexers are declared using *indexer_declaration*s: ```ANTLR @@ -4369,6 +4393,8 @@ Aside from these differences, all rules defined in [§15.7.3](classes.md#1573-ac ### 15.10.1 General +[[§14.10](classes.md#1410-operators) and its subclauses cover operator declarations in classes and structs. That text is augmented by information about declaring operators in interfaces (§interface-operators).] + An ***operator*** is a member that defines the meaning of an expression operator that can be applied to instances of the class. Operators are declared using *operator_declaration*s: ```ANTLR @@ -4917,6 +4943,8 @@ If overload resolution is unable to determine a unique best candidate for the ba ## 15.12 Static constructors +[This subclause covers static constructor declarations in classes. That text is augmented by information about declaring static constructors in structs ([§15.4.10](structs.md#15410-static-constructors)) and in interfaces (§interface-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: ```ANTLR From eaea67f0a21aadf1ad82a1584e607e2a9a785ccb Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 08:47:21 -0500 Subject: [PATCH 03/11] support default interface function members --- standard/classes.md | 12 +- standard/interfaces.md | 350 +++++++++++++++++++++++++++++++++-------- 2 files changed, 286 insertions(+), 76 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 7044e9f0b..8bab78535 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3769,11 +3769,7 @@ An abstract property declaration specifies that the accessors of the property ar 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. -<<<<<<< HEAD -Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). 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. -======= -Abstract property declarations are only permitted in abstract classes ([§14.2.2.2](classes.md#14222-abstract-classes)) and interfaces ([§17.4.3](interfaces.md#1743-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. ->>>>>>> 948e2b0 (support default interface function members) +Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§18.4.3](interfaces.md#1843-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. The override declaration and the overridden base property are required to have the same declared accessibility. In other words, an override declaration may not change the accessibility of the base property. However, if the overridden base property is protected internal and it is declared in a different assembly than the assembly containing the override declaration then the override declaration’s declared accessibility shall be protected. If the inherited property has only a single accessor (i.e., if the inherited property is read-only or write-only), the overriding property shall include only that accessor. If the inherited property includes both accessors (i.e., if the inherited property is read-write), the overriding property can include either a single accessor or both accessors. There shall be an identity conversion between the type of the overriding and the inherited property. @@ -4141,11 +4137,7 @@ An abstract event declaration specifies that the accessors of the event are virt An event declaration that includes both the `abstract` and `override` modifiers specifies that the event is abstract and overrides a base event. The accessors of such an event are also abstract. -<<<<<<< HEAD -Abstract event declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). -======= -Abstract event declarations are only permitted in abstract classes ([§14.2.2.2](classes.md#14222-abstract-classes)) and interfaces ([§17.4.4](interfaces.md#1744-interface-events)). ->>>>>>> 948e2b0 (support default interface function members) +Abstract event declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§18.4.4](interfaces.md#1844-interface-events)). The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an `override` modifier. This is known as an ***overriding event declaration***. An overriding event declaration does not declare a new event. Instead, it simply specializes the implementations of the accessors of an existing virtual event. diff --git a/standard/interfaces.md b/standard/interfaces.md index 9a9bf1c70..d14d0e451 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -4,7 +4,9 @@ An interface defines a contract. A class or struct that implements an interface shall adhere to its contract. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces. -Interfaces can contain methods, properties, events, and indexers. The interface itself does not provide implementations for the members that it declares. The interface merely specifies the members that shall be supplied by classes or structs that implement the interface. +Interfaces may contain various kinds of members, as described in [§17.4](interfaces.md#174-interface-members). The interface itself may provide ***default implementations*** for some or all of the function members that it declares, in which case, those members are *not* part of the interface contract. For those members for which the interface does not provide default implementations, the interface merely specifies the members that shall be supplied by classes or structs that implement the interface. + +> *Note*: Historically, adding a new function member to an interface impacted all existing consumers of that interface type; it was a breaking change! The addition of default interface function member implementations allowed developers to upgrade an interface while still enabling any implementors to override that implementation. Users of the interface can accept the default implementation as a non-breaking change; however, if their requirements are different, they can override the default implementations. *end note* ## 18.2 Interface declarations @@ -222,22 +224,33 @@ The members of an interface are the members inherited from the base interfaces a ```ANTLR interface_member_declaration - : interface_method_declaration - | interface_property_declaration - | interface_event_declaration - | interface_indexer_declaration + : constant_declaration + | field_declaration + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | static_constructor_declaration + | operator_declaration + | type_declaration ; ``` -An interface declaration declares zero or more members. The members of an interface shall be methods, properties, events, or indexers. An interface cannot contain constants, fields, operators, instance constructors, finalizers, or types, nor can an interface contain static members of any kind. +An interface declaration declares zero or more members. The members of an interface shall be constants, fields, methods, properties, events, indexers, operators, constructors, and types, some of which may be instance, others static, as described in the subclauses for each interface member kind. + +All interface members implicitly have public access; however, an explicit access modifier ([§8.5.2](basic-concepts.md#852-declared-accessibility)) is permitted. + +An interface function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be used on a function member that would otherwise be implicitly `virtual`. Similarly, although `abstract` is implied for interface function members without bodies, that modifier may be given explicitly. A non-virtual function member may be declared using the `sealed` keyword. -All interface members implicitly have public access. It is a compile-time error for interface member declarations to include any modifiers. +A `private` or `sealed` function member of an interface shall have a body. A `private` function member shall not have the modifier `sealed`. + +An explicitly implemented function member shall not have the modifier `sealed`. An *interface_declaration* creates a new declaration space ([§7.3](basic-concepts.md#73-declarations)), and the type parameters and *interface_member_declaration*s immediately contained by the *interface_declaration* introduce new members into this declaration space. The following rules apply to *interface_member_declaration*s: - The name of a type parameter in the *type_parameter_list* of an interface declaration shall differ from the names of all other type parameters in the same *type_parameter_list* and shall differ from the names of all members of the interface. -- The name of a method shall differ from the names of all properties and events declared in the same interface. In addition, the signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)) of a method shall differ from the signatures of all other methods declared in the same interface, and two methods declared in the same interface may not have signatures that differ solely by `in`, `out`, and `ref`. -- The name of a property or event shall differ from the names of all other members declared in the same interface. +- The name of a method shall differ from the names of all other kinds of function members declared in the same interface. In addition, the signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)) of a method shall differ from the signatures of all other methods declared in the same interface, and two methods declared in the same interface may not have signatures that differ solely by `in`, `out`, and `ref`. +- The name of a non-function member shall differ from the names of all other non-function member declared in the same interface. - The signature of an indexer shall differ from the signatures of all other indexers declared in the same interface. The inherited members of an interface are specifically not part of the declaration space of the interface. Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. When this occurs, the derived interface member is said to *hide* the base interface member. Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. To suppress the warning, the declaration of the derived interface member shall include a `new` modifier to indicate that the derived member is intended to hide the base member. This topic is discussed further in [§7.7.2.3](basic-concepts.md#7723-hiding-through-inheritance). @@ -248,24 +261,121 @@ If a `new` modifier is included in a declaration that doesn’t hide an inherite The set of members of an interface declared in multiple parts ([§15.2.7](classes.md#1527-partial-declarations)) is the union of the members declared in each part. The bodies of all parts of the interface declaration share the same declaration space ([§7.3](basic-concepts.md#73-declarations)), and the scope of each member ([§7.7](basic-concepts.md#77-scopes)) extends to the bodies of all the parts. -### 18.4.2 Interface methods +Consider an interface with a default implementation for a member `M`. As `M` is not part of that interface’s contract, outside that interface or any interface derived from it, that name is not visible. How then can it be accessed? The following code shows how: -Interface methods are declared using *interface_method_declaration*s: +```csharp +interface IA +{ + public int P { get { return 10; } } + public void M() + { + Console.WriteLine("IA.M"); + } +} -```ANTLR -interface_method_declaration - : attributes? 'new'? return_type interface_method_header - | attributes? 'new'? ref_kind ref_return_type interface_method_header - ; +interface IB : IA +{ + public new int P { get { return 20; } } + void IA.M() + { + Console.WriteLine("IB.M"); + } +} -interface_method_header - : identifier '(' formal_parameter_list? ')' ';' - | identifier type_parameter_list '(' formal_parameter_list? ')' - type_parameter_constraints_clause* ';' - ; +class C : IB { } + +class Test +{ + public static void Start() + { + C c = new C(); + ((IA)c).M(); // cast needed + Console.WriteLine($"IA.P = {((IA)c).P}"); // cast needed + Console.WriteLine($"IB.P = {((IB)c).P}"); // cast needed + } +} ``` -The *attributes*, *return_type*, *ref_return_type*, *identifier*, and *formal_parameter_list* of an interface method declaration have the same meaning as those of a method declaration in a class ([§15.6](classes.md#156-methods)). An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon. +Within the interfaces `IA` and `IB`, member `M` is accessible directly by name. However, within method `Start`, we cannot wrote `c.M()` or `c.P`, as those names are not visible. To find them, casts to the appropriate interface type are needed. + +> *Note*: See how the declaration of `M` in `IB` uses explicit interface implementation syntax. This is necessary to make that method override the one in `IA`; the modifier `override` may not be applied to a function member. *end note* + +### §interface-constants Interface constants + +[§15.4](classes.md#154-constants) covers constant declarations in classes. When declaring constants in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +*constant_declaration* is described in [§15.4](classes.md#154-constants). + +As a *constant_declaration* is considered to have a default implementation ([§18.1](interfaces.md#181-general)), it is *not* part of the interface’s contract. + +See §interface-static-constructors for information regarding the allocation and initialization of constants. + +> *Note*: See §interface-fields for an example of using various kinds of static members declared within an interface. *end note* + +### §interface-fields Interface fields + +[§15.5](classes.md#155-fields) and its subclauses cover field declarations in classes. When declaring fields in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +*field_declaration* is described in [§15.5.1](classes.md#1551-general). + +It is a compile-time error for *field_declaration* to declare an instance field. + +As a static *field_declaration* is considered to have a default implementation ([§18.1](interfaces.md#181-general)), it is *not* part of the interface’s contract. + +> *Example*: The following program contains static members of various kinds: +> +> ```csharp +> using System; +> public interface IX +> { +> private const int constant = 100; +> protected static int field; +> +> static IX() +> { +> Console.WriteLine("static members initialized"); +> Console.WriteLine($"constant = {IX.constant}, field = {IX.field}"); +> field = 50; +> Console.WriteLine("static constructor has run"); +> } +> +> public static void Main() +> { +> Console.WriteLine($"constant = {IX.constant}, field = {IX.field}"); +> } +> } +> ``` +> +> The output produced is +> +> ```console +> static members initialized +> constant = 100, field = 0 +> static constructor has run +> constant = 100, field = 50 +> ``` +> +> *end example* + +See §interface-static-constructors for information regarding the allocation and initialization of static fields. + +### 18.4.2 Interface methods + +[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. When declaring methods in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +Interface methods are declared using *method_declaration*s ([§15.6.1](classes.md#1561-general)). + +*method_modifier* shall not include `override`. + +An interface method declaration that has a *block* as a *method_body* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. An *method_declaration* shall not have *type_parameter_constraints_clause*s unless it also has a *type_parameter_list*. + +The list of requirements for valid combinations of modifiers stated for a class method is extended, as follows: + +- A static declaration that is not extern or abstract shall have a *block* as a *method_body*. +- A virtual declaration that is not extern shall have a *block* as a *method_body*. +- A private declaration that is not extern shall have a *block* as a *method_body*. +- A sealed declaration that is not extern shall have a *block* as a *method_body*. +- An async declaration shall have a *block* as a *method_body*. All formal parameter types of an interface method shall be input-safe ([§18.2.3.2](interfaces.md#18232-variance-safety)), and the return type shall be either `void` or output-safe. In addition, any output or reference formal parameter types shall also be output-safe. @@ -312,64 +422,131 @@ These rules ensure that any covariant or contravariant usage of the interface re > > *end example* -### 18.4.3 Interface properties +> *Note*: See §interface-fields for an example that not only shows a static method with default implementation, but as that method is called `Main` and has the right return type and signature, it’s also an entry point! *end note* -Interface properties are declared using *interface_property_declaration*s: +A virtual method with implementation declared in an interface may be overridden to be abstract in a derived interface. This is known as ***reabstraction***. -```ANTLR -interface_property_declaration - : attributes? 'new'? type identifier '{' interface_accessors '}' - | attributes? 'new'? ref_kind type identifier '{' ref_interface_accessor '}' - ; +> *Example*: +> +> ```csharp +> interface IA +> { +> void M() { Console.WriteLine("IA.M"); } +> } +> +> interface IB : IA +> { +> abstract void IA.M(); // reabstraction of M +> } +> ``` +> +> This is useful in derived interfaces where the default implementation of a method is inappropriate and a more appropriate implementation should be provided by implementing classes. *end example* -interface_accessors - : attributes? 'get' ';' - | attributes? 'set' ';' - | attributes? 'get' ';' attributes? 'set' ';' - | attributes? 'set' ';' attributes? 'get' ';' - ; +Reabstraction is also permissible in an implementing class. -ref_interface_accessor - : attributes? 'get' ';' - ; -``` +> *Example*: +> +> ```csharp +> interface I1 +> { +> void M() { } +> } +> +> abstract class C : I1 +> { +> public abstract void M(); // implement I1.M with an abstract method in C +> } +> ``` +> +> *end example* + +Every interface and class shall have a most specific override for every virtual member among the overrides appearing in the type or its direct and indirect interfaces. The ***most specific override*** is a unique override that is more specific than every other override. If there is no override, the member itself is considered the most specific override. + +One override `M1` is considered *more specific* than another override `M2` if `M1` is declared on type `T1`, `M2` is declared on type `T2`, and either + +1. `T1` contains `T2` among its direct or indirect interfaces, or +1. `T2` is an interface type but `T1` is not an interface type. + +> *Example*: +> +> ```csharp +> interface IA +> { +> void M() { Console.WriteLine("IA.M"); } +> } +> +> interface IB : IA +> { +> void IA.M() { Console.WriteLine("IB.M"); } +> } +> +> interface IC : IA +> { +> void IA.M() { Console.WriteLine("IC.M"); } +> } +> +> abstract class C : IB, IC { } // error: no most specific override for 'IA.M' +> +> abstract class D : IA, IB, IC // OK +> { +> public abstract void M(); +> } +> ``` +> +> The most specific override rule ensures that a conflict (i.e., an ambiguity arising from diamond inheritance) is resolved explicitly by the programmer at the point where the conflict arises. *end example* + +It is an error if in a class declaration the most specific override of some interface method is an abstract override that was declared in an interface. + +> *Example*: +> +> ```csharp +> interface IF +> { +> void M(); +> } +> +> abstract class F : IF { } // error: 'F' does not implement 'IF.M' +> ``` +> +> *end example* + +### 18.4.3 Interface properties + +[§15.7](classes.md#157-properties) and its subclauses cover property declarations in classes. When declaring properties in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +Interface properties are declared using *property_declaration*s ([§15.7.1](classes.md#1571-general)). -The *attributes*, *type*, and *identifier* of an interface property declaration have the same meaning as those of a property declaration in a class ([§15.7](classes.md#157-properties)). +*property_modifier* shall not include `override`. -The accessors of an interface property declaration correspond to the accessors of a class property declaration ([§15.7.3](classes.md#1573-accessors)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only. +A *property_declaration* that has a *block* as an *accessor_body* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. A *property_declaration* that has no default implementation is always considered part of the interface’s contract; it is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). + +> *Note*: As an interface cannot contain instance fields, an interface property cannot be an instance auto-property, as that would require the declaration of implicit hidden instance fields. *end note* The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. ### 18.4.4 Interface events -Interface events are declared using *interface_event_declaration*s: +[§15.8](classes.md#158-events) and its subclauses cover event declarations in classes and structs. When declaring events in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. -```ANTLR -interface_event_declaration - : attributes? 'new'? 'event' type identifier ';' - ; -``` +Interface events are declared using *event_declaration*s ([§15.8.1](classes.md#1581-general)). + +*event_modifier* shall not include `override`. -The *attributes*, *type*, and *identifier* of an interface event declaration have the same meaning as those of an event declaration in a class ([§15.8](classes.md#158-events)). +An *event_declaration* that has an *event_accessor_declarations* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. An *event_declaration* that has no default implementation is always considered part of the interface’s contract; it is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)). + +It is a compile-time error for *variable_declarators* in an instance *event_declaration* to contain any *variable_initializer*s. The type of an interface event shall be input-safe. ### 18.4.5 Interface indexers -Interface indexers are declared using *interface_indexer_declaration*s: +[§15.9](classes.md#159-indexers) and its subclauses cover index declarations in classes. When declaring indexers in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. -```ANTLR -interface_indexer_declaration - : attributes? 'new'? type 'this' '[' formal_parameter_list ']' - '{' interface_accessors '}' - | attributes? 'new'? ref_kind type 'this' '[' formal_parameter_list ']' - '{' ref_interface_accessor '}' - ; -``` +Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.md#159-indexers)). -The *attributes*, *type*, and *formal_parameter_list* of an interface indexer declaration have the same meaning as those of an indexer declaration in a class ([§15.9](classes.md#159-indexers)). +*indexer_modifier* shall not include `override`. -The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration ([§15.9](classes.md#159-indexers)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only. +An *indexer_declaration* that has a *block* as an *accessor_body* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. All the formal parameter types of an interface indexer shall be input-safe ([§18.2.3.2](interfaces.md#18232-variance-safety)). In addition, any output or reference formal parameter types shall also be output-safe. @@ -377,9 +554,50 @@ All the formal parameter types of an interface indexer shall be input-safe ([§1 The type of an interface indexer shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. +### §interface-operators Interface operators + +[§14.10](classes.md#1410-operators) and its subclauses cover operator declarations in classes and structs. When declaring operators in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +An *operator_declaration* is a default implementation ([§17.1](interfaces.md#171-general)), so it is *not* part of the interface’s contract. + +It is a compile-time error for an interface to contain a conversion, equality, or inequality operator. + +### §interface-static-constructors Interface static constructors + +[§14.12](classes.md#1412-static-constructors) covers static constructor declarations in classes. When declaring static constructors in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +A *static_constructor_declaration* that has a *block* as a *static_constructor_body* is a default implementation ([§17.1](interfaces.md#171-general)), so it is *not* part of the interface’s contract. + +The static constructor for a closed interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain: + +- Any of the static members of the interface are referenced. +- Before the Main method is called for an interface containing the Main method ([§8.1](basic-concepts.md#81-application-startup)) in which execution begins. + +To initialize a new closed interface type, first a new set of static fields for that particular closed type is created. Each of the static fields is initialized to its default value. Next, the static field initializers are executed for those static fields. Finally, the static constructor is executed. + +> *Note*: See §interface-fields for an example of using various kinds of static members (including a Main method) declared within an interface. *end note* + +### §interface-nested-types Interface nested types + +[§14.3.9](classes.md#1439-nested-types) covers nested types in classes and structs. When declaring nested types in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. + +It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§17.2.3.1](interfaces.md#17231-general)). + +> *Example*: The declaration of `C` below is an error. +> +> ```csharp +> interface IOuter +> { +> class C { } // error: class declaration within scope of variant type parameter 'T' +> } +> ``` +> +> *end example* + ### 18.4.6 Interface member access -Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a method, property, or event of that interface type, and `A` is an indexer argument list. +Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list.### 17.4.6 Interface member access + For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.9.2](expressions.md#12892-method-invocations)), and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which don’t. In all cases, explicit casts can be used to resolve the ambiguities. @@ -608,7 +826,7 @@ The base interfaces of a generic class declaration shall satisfy the uniqueness ### 18.6.2 Explicit interface member implementations -For purposes of implementing interfaces, a class or struct may declare ***explicit interface member implementations***. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. +For purposes of implementing interfaces, a class, struct, or interface may declare ***explicit interface member implementations***. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. > *Example*: > @@ -662,7 +880,7 @@ For purposes of implementing interfaces, a class or struct may declare ***explic > > *end example* -It is not possible to access an explicit interface member implementation through its qualified interface member name in a method invocation, property access, event access, or indexer access. An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name. +It is not possible to access an explicit interface member implementation through its qualified interface member name in a method invocation, property access, event access, or indexer access. An explicit instance interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name. An explicit interface static member implementation can only be accessed through the interface name. It is a compile-time error for an explicit interface member implementation to include any modifiers ([§15.6](classes.md#156-methods)) other than `extern` or `async`. @@ -672,11 +890,11 @@ It is a compile-time error for an explicit interface method implementation to in > Explicit interface member implementations serve two primary purposes: > > - Because explicit interface member implementations are not accessible through class or struct instances, they allow interface implementations to be excluded from the public interface of a class or struct. This is particularly useful when a class or struct implements an internal interface that is of no interest to a consumer of that class or struct. -> - Explicit interface member implementations allow disambiguation of interface members with the same signature. Without explicit interface member implementations it would be impossible for a class or struct to have different implementations of interface members with the same signature and return type, as would it be impossible for a class or struct to have any implementation at all of interface members with the same signature but with different return types. +> - Explicit interface member implementations allow disambiguation of interface members with the same signature. Without explicit interface member implementations it would be impossible for a class, struct, or interface to have different implementations of interface members with the same signature and return type, as would it be impossible for a class, struct, or interface to have any implementation at all of interface members with the same signature but with different return types. > > *end note* -For an explicit interface member implementation to be valid, the class or struct shall name an interface in its base class list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter array, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter array then an associated explicit interface member implementation shall not have a parameter array. +For an explicit interface member implementation to be valid, the class, struct, or interface shall name an interface in its base class or base interface list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter array, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter array then an associated explicit interface member implementation shall not have a parameter array. > *Example*: Thus, in the following class > @@ -852,7 +1070,7 @@ When a generic method implicitly implements an interface method, the constraints ### 18.6.5 Interface mapping -A class or struct shall provide implementations of all members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as ***interface mapping***. +A class or struct shall provide implementations of all contract members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as ***interface mapping***. Interface mapping for a class or struct `C` locates an implementation for each member of each interface specified in the base class list of `C`. The implementation of a particular interface member `I.M`, where `I` is the interface in which the member `M` is declared, is determined by examining each class or struct `S`, starting with `C` and repeating for each successive base class of `C`, until a match is located: @@ -1249,7 +1467,7 @@ When a class implements an interface, it implicitly also implements all that int ### 18.6.8 Abstract classes and interfaces -Like a non-abstract class, an abstract class shall provide implementations of all members of the interfaces that are listed in the base class list of the class. However, an abstract class is permitted to map interface methods onto abstract methods. +Like a non-abstract class, an abstract class shall provide implementations of all contract members of the interfaces that are listed in the base class list of the class. However, an abstract class is permitted to map interface methods onto abstract methods. > *Example*: > From 0b9e3fafd67d15a4487c7f72a6fccb82be26cef9 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 09:02:46 -0500 Subject: [PATCH 04/11] Update classes.md --- standard/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index 8bab78535..24bfbc85f 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3867,7 +3867,7 @@ When a property is declared as an override, any overridden accessors shall be ac ### 15.8.1 General -[[§14.8](classes.md#14-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§17.4.4](interfaces.md#1744-interface-events)).] +[[§14.8](classes.md#148-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§17.4.4](interfaces.md#1744-interface-events)).] An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handlers***. From 5293f942c64ecbfef649d10e44eaf2fed7d0a040 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 09:06:39 -0500 Subject: [PATCH 05/11] Update interfaces.md --- standard/interfaces.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/interfaces.md b/standard/interfaces.md index d14d0e451..bdcd26cec 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -238,7 +238,7 @@ interface_member_declaration An interface declaration declares zero or more members. The members of an interface shall be constants, fields, methods, properties, events, indexers, operators, constructors, and types, some of which may be instance, others static, as described in the subclauses for each interface member kind. -All interface members implicitly have public access; however, an explicit access modifier ([§8.5.2](basic-concepts.md#852-declared-accessibility)) is permitted. +All interface members implicitly have public access; however, an explicit access modifier ([§7.5.2](basic-concepts.md#752-declared-accessibility)) is permitted. An interface function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be used on a function member that would otherwise be implicitly `virtual`. Similarly, although `abstract` is implied for interface function members without bodies, that modifier may be given explicitly. A non-virtual function member may be declared using the `sealed` keyword. @@ -571,7 +571,7 @@ A *static_constructor_declaration* that has a *block* as a *static_constructor_b The static constructor for a closed interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain: - Any of the static members of the interface are referenced. -- Before the Main method is called for an interface containing the Main method ([§8.1](basic-concepts.md#81-application-startup)) in which execution begins. +- Before the Main method is called for an interface containing the Main method ([§7.1](basic-concepts.md#71-application-startup)) in which execution begins. To initialize a new closed interface type, first a new set of static fields for that particular closed type is created. Each of the static fields is initialized to its default value. Next, the static field initializers are executed for those static fields. Finally, the static constructor is executed. From fa1a1fb26eedd11c5d8ceced63404b2e4e621fa5 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 5 Dec 2022 09:15:16 -0500 Subject: [PATCH 06/11] Update interfaces.md --- standard/interfaces.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/standard/interfaces.md b/standard/interfaces.md index bdcd26cec..7e6b923f3 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -371,11 +371,11 @@ An interface method declaration that has a *block* as a *method_body* is a defau The list of requirements for valid combinations of modifiers stated for a class method is extended, as follows: -- A static declaration that is not extern or abstract shall have a *block* as a *method_body*. -- A virtual declaration that is not extern shall have a *block* as a *method_body*. -- A private declaration that is not extern shall have a *block* as a *method_body*. -- A sealed declaration that is not extern shall have a *block* as a *method_body*. -- An async declaration shall have a *block* as a *method_body*. +- A static declaration that is not extern or abstract shall have a *block* as a *method_body*. +- A virtual declaration that is not extern shall have a *block* as a *method_body*. +- A private declaration that is not extern shall have a *block* as a *method_body*. +- A sealed declaration that is not extern shall have a *block* as a *method_body*. +- An async declaration shall have a *block* as a *method_body*. All formal parameter types of an interface method shall be input-safe ([§18.2.3.2](interfaces.md#18232-variance-safety)), and the return type shall be either `void` or output-safe. In addition, any output or reference formal parameter types shall also be output-safe. @@ -421,7 +421,9 @@ These rules ensure that any covariant or contravariant usage of the interface re > This is actually a call to `C.M`. But that call requires that `E` derive from `D`, so type safety would be violated here. > > *end example* + + > *Note*: See §interface-fields for an example that not only shows a static method with default implementation, but as that method is called `Main` and has the right return type and signature, it’s also an entry point! *end note* A virtual method with implementation declared in an interface may be overridden to be abstract in a derived interface. This is known as ***reabstraction***. From dc8d7a092c8863b6ae85959ca14af8dc6e310afb Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 22 Jan 2023 15:30:57 -0500 Subject: [PATCH 07/11] add annotation to new examples --- standard/interfaces.md | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/standard/interfaces.md b/standard/interfaces.md index 7e6b923f3..cbc5ca2a8 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -263,6 +263,7 @@ The set of members of an interface declared in multiple parts ([§15.2.7](classe Consider an interface with a default implementation for a member `M`. As `M` is not part of that interface’s contract, outside that interface or any interface derived from it, that name is not visible. How then can it be accessed? The following code shows how: + ```csharp interface IA { @@ -273,7 +274,7 @@ interface IA } } -interface IB : IA +interface IB: IA { public new int P { get { return 20; } } void IA.M() @@ -282,11 +283,11 @@ interface IB : IA } } -class C : IB { } +class C: IB { } class Test { - public static void Start() + public static void Main() { C c = new C(); ((IA)c).M(); // cast needed @@ -324,11 +325,11 @@ As a static *field_declaration* is considered to have a default implementation ( > *Example*: The following program contains static members of various kinds: > +> > ```csharp -> using System; > public interface IX > { -> private const int constant = 100; +> public const int constant = 100; > protected static int field; > > static IX() @@ -338,7 +339,10 @@ As a static *field_declaration* is considered to have a default implementation ( > field = 50; > Console.WriteLine("static constructor has run"); > } -> +> } +> +> public class Test: IX +> { > public static void Main() > { > Console.WriteLine($"constant = {IX.constant}, field = {IX.field}"); @@ -405,9 +409,9 @@ These rules ensure that any covariant or contravariant usage of the interface re > > ```csharp > class B {} -> class D : B {} -> class E : B {} -> class C : I +> class D: B {} +> class E: B {} +> class C: I > { > public void M() {...} > } @@ -430,13 +434,14 @@ A virtual method with implementation declared in an interface may be overridden > *Example*: > +> > ```csharp > interface IA > { > void M() { Console.WriteLine("IA.M"); } > } > -> interface IB : IA +> interface IB: IA > { > abstract void IA.M(); // reabstraction of M > } @@ -448,13 +453,14 @@ Reabstraction is also permissible in an implementing class. > *Example*: > +> > ```csharp > interface I1 > { > void M() { } > } > -> abstract class C : I1 +> abstract class C: I1 > { > public abstract void M(); // implement I1.M with an abstract method in C > } @@ -471,6 +477,7 @@ One override `M1` is considered *more specific* than another override `M2` if `M > *Example*: > +> > ```csharp > interface IA > { @@ -482,14 +489,14 @@ One override `M1` is considered *more specific* than another override `M2` if `M > void IA.M() { Console.WriteLine("IB.M"); } > } > -> interface IC : IA +> interface IC: IA > { > void IA.M() { Console.WriteLine("IC.M"); } > } > -> abstract class C : IB, IC { } // error: no most specific override for 'IA.M' +> abstract class C: IB, IC { } // error: no most specific override for 'IA.M' > -> abstract class D : IA, IB, IC // OK +> abstract class D: IA, IB, IC // OK > { > public abstract void M(); > } @@ -501,6 +508,7 @@ It is an error if in a class declaration the most specific override of some inte > *Example*: > +> > ```csharp > interface IF > { @@ -587,6 +595,7 @@ It is an error to declare a class type, struct type, or enum type within the sco > *Example*: The declaration of `C` below is an error. > +> > ```csharp > interface IOuter > { From e2f259196e7e65fb9a806f86ecf7586c7599dbd9 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 25 Sep 2023 17:14:21 -0400 Subject: [PATCH 08/11] first pass at fixing references --- standard/classes.md | 12 ++++++------ standard/interfaces.md | 15 +++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 24bfbc85f..f9b89775a 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -1484,7 +1484,7 @@ Constant declarations may depend on constants from other programs, but such depe ### 15.5.1 General -[[§14.5](classes.md#145-fields) and its subclauses cover field declarations in classes. That text is augmented by information about declaring fields in structs ([§15.4.1](structs.md#1541-general)) and interfaces (§interface-fields).] +[[§15.5](classes.md#155-fields) and its subclauses cover field declarations in classes. That text is augmented by information about declaring fields in structs ([§16.4.1](structs.md#1641-general)) and interfaces (§interface-fields).] A ***field*** is a member that represents a variable associated with an object or class. A *field_declaration* introduces one or more fields of a given type. @@ -1909,7 +1909,7 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General -[[§14.6](classes.md#146-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§15.4](structs.md#154-class-and-struct-differences)) and interfaces ([§17.4.2](interfaces.md#1742-interface-methods)).] +[[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.4](structs.md#164-class-and-struct-differences)) and interfaces ([§18.4.2](interfaces.md#1842-interface-methods)).] A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: @@ -3123,7 +3123,7 @@ For returns-by-value and returns-by-ref methods the endpoint of the method body ### 15.7.1 General -[[§14.7](classes.md#147-properties) and its subclauses cover property declarations in classes. That text is augmented by information about declaring properties in structs ([§15.4](structs.md#154-class-and-struct-differences)) and in interfaces ([§17.4.3](interfaces.md#1743-interface-properties)).] +[[§15.7](classes.md#157-properties) and its subclauses cover property declarations in classes. That text is augmented by information about declaring properties in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.3](interfaces.md#1843-interface-properties)).] A ***property*** is a member that provides access to a characteristic of an object or a class. Examples of properties include the length of a string, the size of a font, the caption of a window, the name of a customer, and so on. Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties do not denote storage locations. Instead, properties have ***accessors*** that specify the statements to be executed when their values are read or written. Properties thus provide a mechanism for associating actions with the reading and writing of an object’s characteristics; furthermore, they permit such characteristics to be computed. @@ -3867,7 +3867,7 @@ When a property is declared as an override, any overridden accessors shall be ac ### 15.8.1 General -[[§14.8](classes.md#148-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§17.4.4](interfaces.md#1744-interface-events)).] +[[§15.8](classes.md#158-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§18.4.4](interfaces.md#1844-interface-events)).] An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handlers***. @@ -4153,7 +4153,7 @@ Except for differences in declaration and invocation syntax, virtual, sealed, ov ### 15.9.1 General -[This subclause covers indexer declarations in classes. That text is augmented by information about declaring indexers in structs ([§15.4](structs.md#154-class-and-struct-differences)) and in interfaces ([§17.4.5](interfaces.md#1745-interface-indexers)).] +[This subclause covers indexer declarations in classes. That text is augmented by information about declaring indexers in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.5](interfaces.md#1845-interface-indexers)).] An ***indexer*** is a member that enables an object to be indexed in the same way as an array. Indexers are declared using *indexer_declaration*s: @@ -4385,7 +4385,7 @@ Aside from these differences, all rules defined in [§15.7.3](classes.md#1573-ac ### 15.10.1 General -[[§14.10](classes.md#1410-operators) and its subclauses cover operator declarations in classes and structs. That text is augmented by information about declaring operators in interfaces (§interface-operators).] +[[§15.10](classes.md#1510-operators) and its subclauses cover operator declarations in classes and structs. That text is augmented by information about declaring operators in interfaces (§interface-operators).] An ***operator*** is a member that defines the meaning of an expression operator that can be applied to instances of the class. Operators are declared using *operator_declaration*s: diff --git a/standard/interfaces.md b/standard/interfaces.md index cbc5ca2a8..5839b912d 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -566,17 +566,17 @@ The type of an interface indexer shall be output-safe if there is a get accessor ### §interface-operators Interface operators -[§14.10](classes.md#1410-operators) and its subclauses cover operator declarations in classes and structs. When declaring operators in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. +[§15.10](classes.md#1510-operators) and its subclauses cover operator declarations in classes and structs. When declaring operators in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. -An *operator_declaration* is a default implementation ([§17.1](interfaces.md#171-general)), so it is *not* part of the interface’s contract. +An *operator_declaration* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. It is a compile-time error for an interface to contain a conversion, equality, or inequality operator. ### §interface-static-constructors Interface static constructors -[§14.12](classes.md#1412-static-constructors) covers static constructor declarations in classes. When declaring static constructors in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. +[§15.12](classes.md#1512-static-constructors) covers static constructor declarations in classes. When declaring static constructors in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. -A *static_constructor_declaration* that has a *block* as a *static_constructor_body* is a default implementation ([§17.1](interfaces.md#171-general)), so it is *not* part of the interface’s contract. +A *static_constructor_declaration* that has a *block* as a *static_constructor_body* is a default implementation ([§18.1](interfaces.md#181-general)), so it is *not* part of the interface’s contract. The static constructor for a closed interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain: @@ -589,9 +589,9 @@ To initialize a new closed interface type, first a new set of static fields for ### §interface-nested-types Interface nested types -[§14.3.9](classes.md#1439-nested-types) covers nested types in classes and structs. When declaring nested types in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. +[§15.3.9](classes.md#1539-nested-types) covers nested types in classes and structs. When declaring nested types in interfaces, that text needs to be interpreted in the context of an interface, and, where necessary, it is augmented and/or replaced by text in this subclause. -It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§17.2.3.1](interfaces.md#17231-general)). +It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§18.2.3.1](interfaces.md#18231-general)). > *Example*: The declaration of `C` below is an error. > @@ -607,8 +607,7 @@ It is an error to declare a class type, struct type, or enum type within the sco ### 18.4.6 Interface member access -Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list.### 17.4.6 Interface member access - +Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.9.2](expressions.md#12892-method-invocations)), and indexer access ([§12.8.11.3](expressions.md#128113-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which don’t. In all cases, explicit casts can be used to resolve the ambiguities. From 80a16dbb3913ceb41ae24ca079cdfeab292778f5 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 25 Sep 2023 17:31:00 -0400 Subject: [PATCH 09/11] find link errors part 2 --- standard/classes.md | 2 +- standard/interfaces.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index f9b89775a..8405b7b4d 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -4935,7 +4935,7 @@ If overload resolution is unable to determine a unique best candidate for the ba ## 15.12 Static constructors -[This subclause covers static constructor declarations in classes. That text is augmented by information about declaring static constructors in structs ([§15.4.10](structs.md#15410-static-constructors)) and in interfaces (§interface-static-constructors).] +[This subclause covers static constructor declarations in classes. That text is augmented by information about declaring static constructors in structs ([§16.4.10](structs.md#16410-static-constructors)) and in interfaces (§interface-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: diff --git a/standard/interfaces.md b/standard/interfaces.md index 5839b912d..774142ba9 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -4,7 +4,7 @@ An interface defines a contract. A class or struct that implements an interface shall adhere to its contract. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces. -Interfaces may contain various kinds of members, as described in [§17.4](interfaces.md#174-interface-members). The interface itself may provide ***default implementations*** for some or all of the function members that it declares, in which case, those members are *not* part of the interface contract. For those members for which the interface does not provide default implementations, the interface merely specifies the members that shall be supplied by classes or structs that implement the interface. +Interfaces may contain various kinds of members, as described in [§18.4](interfaces.md#184-interface-members). The interface itself may provide ***default implementations*** for some or all of the function members that it declares, in which case, those members are *not* part of the interface contract. For those members for which the interface does not provide default implementations, the interface merely specifies the members that shall be supplied by classes or structs that implement the interface. > *Note*: Historically, adding a new function member to an interface impacted all existing consumers of that interface type; it was a breaking change! The addition of default interface function member implementations allowed developers to upgrade an interface while still enabling any implementors to override that implementation. Users of the interface can accept the default implementation as a non-breaking change; however, if their requirements are different, they can override the default implementations. *end note* From 230888fa04729e08d4bc35231bc29b3e34da4862 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 25 Sep 2023 17:37:55 -0400 Subject: [PATCH 10/11] word converter warnings Enclosing a paragraph in brackets breaks the word converter. It looks for a link. --- standard/classes.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 8405b7b4d..835f069a0 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -1484,7 +1484,7 @@ Constant declarations may depend on constants from other programs, but such depe ### 15.5.1 General -[[§15.5](classes.md#155-fields) and its subclauses cover field declarations in classes. That text is augmented by information about declaring fields in structs ([§16.4.1](structs.md#1641-general)) and interfaces (§interface-fields).] +[§15.5](classes.md#155-fields) and its subclauses cover field declarations in classes. That text is augmented by information about declaring fields in structs ([§16.4.1](structs.md#1641-general)) and interfaces (§interface-fields). A ***field*** is a member that represents a variable associated with an object or class. A *field_declaration* introduces one or more fields of a given type. @@ -1909,7 +1909,7 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General -[[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.4](structs.md#164-class-and-struct-differences)) and interfaces ([§18.4.2](interfaces.md#1842-interface-methods)).] +[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.4](structs.md#164-class-and-struct-differences)) and interfaces ([§18.4.2](interfaces.md#1842-interface-methods)). A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: @@ -3123,7 +3123,7 @@ For returns-by-value and returns-by-ref methods the endpoint of the method body ### 15.7.1 General -[[§15.7](classes.md#157-properties) and its subclauses cover property declarations in classes. That text is augmented by information about declaring properties in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.3](interfaces.md#1843-interface-properties)).] +[§15.7](classes.md#157-properties) and its subclauses cover property declarations in classes. That text is augmented by information about declaring properties in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.3](interfaces.md#1843-interface-properties)). A ***property*** is a member that provides access to a characteristic of an object or a class. Examples of properties include the length of a string, the size of a font, the caption of a window, the name of a customer, and so on. Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties do not denote storage locations. Instead, properties have ***accessors*** that specify the statements to be executed when their values are read or written. Properties thus provide a mechanism for associating actions with the reading and writing of an object’s characteristics; furthermore, they permit such characteristics to be computed. @@ -3867,7 +3867,7 @@ When a property is declared as an override, any overridden accessors shall be ac ### 15.8.1 General -[[§15.8](classes.md#158-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§18.4.4](interfaces.md#1844-interface-events)).] +[§15.8](classes.md#158-events) and its subclauses cover event declarations in classes and structs. That text is augmented by information about declaring events in interfaces ([§18.4.4](interfaces.md#1844-interface-events)). An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handlers***. @@ -4153,7 +4153,7 @@ Except for differences in declaration and invocation syntax, virtual, sealed, ov ### 15.9.1 General -[This subclause covers indexer declarations in classes. That text is augmented by information about declaring indexers in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.5](interfaces.md#1845-interface-indexers)).] +This subclause covers indexer declarations in classes. That text is augmented by information about declaring indexers in structs ([§16.4](structs.md#164-class-and-struct-differences)) and in interfaces ([§18.4.5](interfaces.md#1845-interface-indexers)). An ***indexer*** is a member that enables an object to be indexed in the same way as an array. Indexers are declared using *indexer_declaration*s: @@ -4385,7 +4385,7 @@ Aside from these differences, all rules defined in [§15.7.3](classes.md#1573-ac ### 15.10.1 General -[[§15.10](classes.md#1510-operators) and its subclauses cover operator declarations in classes and structs. That text is augmented by information about declaring operators in interfaces (§interface-operators).] +[§15.10](classes.md#1510-operators) and its subclauses cover operator declarations in classes and structs. That text is augmented by information about declaring operators in interfaces (§interface-operators). An ***operator*** is a member that defines the meaning of an expression operator that can be applied to instances of the class. Operators are declared using *operator_declaration*s: @@ -4935,7 +4935,7 @@ If overload resolution is unable to determine a unique best candidate for the ba ## 15.12 Static constructors -[This subclause covers static constructor declarations in classes. That text is augmented by information about declaring static constructors in structs ([§16.4.10](structs.md#16410-static-constructors)) and in interfaces (§interface-static-constructors).] +This subclause covers static constructor declarations in classes. That text is augmented by information about declaring static constructors in structs ([§16.4.10](structs.md#16410-static-constructors)) and in interfaces (§interface-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 30023736ca8a1f8b2395eed1d8b9f6c6b2dbf7d1 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 25 Aug 2024 15:40:42 -0400 Subject: [PATCH 11/11] minor tweaks --- standard/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index 835f069a0..49aa5cfed 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -1388,7 +1388,7 @@ void Finalize(); ## 15.4 Constants -[This subclause covers constant declarations in classes and structs. That text is augmented by information about declaring constants in interfaces (§interface-constants).] +This subclause covers constant declarations in classes and structs. That text is augmented by information about declaring constants in interfaces (§interface-constants). A ***constant*** is a class member that represents a constant value: a value that can be computed at compile-time. A *constant_declaration* introduces one or more constants of a given type.