Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .github/workflows/dependencies/GrammarTestingEnv.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion standard/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ As described in [§7.4](basic-concepts.md#74-members), all members of a base cla

### 7.5.4 Protected access

When a `protected` or `private protected` instance member is accessed outside the program text of the class in which it is declared, and when a `protected internal` instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place *through* an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. Instance interface members defined with `protected` or `private protected` access cannot be accessed from a `class` or `struct` that implements that interface; these can be accessed only from derived interfaces. However, `class` and `struct` types can define overridden `protected` instance members declared in an interface it implements.
When a `protected` or `private protected` instance member is accessed outside the program text of the class in which it is declared, and when a `protected internal` instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place *through* an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. Instance interface members defined with `protected` or `private protected` access cannot be accessed from a `class` or `struct` that implements that interface; these can be accessed only from derived interfaces. However, `class` and `struct` types can implement `protected` instance members declared in an interface they implement.

Let `B` be a base class that declares a protected instance member `M`, and let `D` be a class that derives from `B`. Within the *class_body* of `D`, access to `M` can take one of the following forms:

Expand Down
3 changes: 2 additions & 1 deletion standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ The direct base class of a class type shall be at least as accessible as the cla

The direct base class of a class type shall not be any of the following types: `System.Array`, `System.Delegate`, `System.Enum`, `System.ValueType` or the `dynamic` type. Furthermore, a generic class declaration shall not use `System.Attribute` as a direct or indirect base class ([§23.2.1](attributes.md#2321-general)).

In determining the meaning of the direct base class specification `A` of a class `B`, the direct base class of `B` is temporarily assumed to be `object`, which ensures that the meaning of a base class specification cannot recursively depend on itself.
In determining the meaning of the direct base class specification `A` of a class `B`, the direct base class of `B` is temporarily assumed to be `object`, which ensures that the meaning of a base class specification cannot recursively depend on itself. Given this definition, the complete set of types upon which a class depends is the transitive closure of the *directly depends on* relationship.

> *Example*: The following
>
Expand Down Expand Up @@ -3426,6 +3426,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 explicit interface member implementation.
- The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* ([§16.4.11](structs.md#16411-properties), [§16.4.13](structs.md#16413-indexers)).
- 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.
Expand Down
18 changes: 9 additions & 9 deletions standard/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [§19.4](interfaces.md#194-interface-members). The interface itself may provide an implementation for some or all of the function members that it declares. Members for which the interface does not provide an implementation are abstract. Their implementations must be supplied by classes or structs that implement the interface, or derived interface that provide an overriding definition.
Interfaces may contain various kinds of members, as described in [§19.4](interfaces.md#194-interface-members). The interface itself may provide an implementation for some or all of the function members that it declares. Members for which the interface does not provide an implementation are abstract. Their implementations must be supplied by classes or structs that implement the interface, and may be supplied by derived interfaces through an explicit implementation ([§19.6.2](interfaces.md#1962-explicit-interface-member-implementations)).

<!-- This note needs to be updated in C# 13, when ref struct types can implement interfaces. -->
> *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 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 implementation as a non-breaking change; however, if their requirements are different, they can override the provided implementations. *end note*
Expand Down Expand Up @@ -233,12 +233,12 @@ interface_member_declaration
;
```

This clause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with restrictions for interfaces. The Interface members are declared using *member_declaration*s with the following additional rules:
This clause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with the differences and restrictions for interfaces:

- A *finalizer_declaration* is not allowed.
- Instance constructors, *constructor_declaration*s, are not allowed.
- All interface members implicitly have public access; however, an explicit access modifier ([§7.5.2](basic-concepts.md#752-declared-accessibility)) is permitted except on static constructors ([§15.12](classes.md#1512-static-constructors)).
- The `abstract` modifier is implied for interface function members without bodies; that modifier may be given explicitly.
- The `abstract` modifier is implied for interface function members ([§12.6](expressions.md#126-function-members)) without bodies; that modifier may be given explicitly.
- An interface instance 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 given explicitly.
- A `private` or `sealed` function member of an interface shall have a body.
- A `private` function member shall not have the modifier `sealed`.
Expand Down Expand Up @@ -476,7 +476,7 @@ Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.m

This clause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces.

An *operator_declaration* in an interface is the implementation ([§19.1](interfaces.md#191-general)).
For an *operator_declaration* in an interface the *operator_body* shall only be a block body ([§15.6.1](classes.md#1561-general)) or an expression body ([§15.6.1](classes.md#1561-general)).

It is a compile-time error for an interface to declare a conversion, equality, or inequality operator.

Expand Down Expand Up @@ -514,7 +514,7 @@ It is an error to declare a class type, struct type, or enum type within the sco
>
> *end example*

### 19.4.10 most specific implementation
### 19.4.10 Most specific implementation

Every class and struct shall have a most specific implementation for every virtual member declared in all interfaces implemented by that type among the implementations appearing in the type or its direct and indirect interfaces. The ***most specific implementation*** is a unique implementation that is more specific than every other implementation.

Expand Down Expand Up @@ -886,7 +886,7 @@ A *type_parameter_constraints_clause* on an explicit interface method implementa
> 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, 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.
> - 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; and it would 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*

Expand Down Expand Up @@ -1066,7 +1066,7 @@ When a generic method implicitly implements an interface method, the constraints

### 19.6.5 Interface mapping

A class or struct shall provide implementations of all abstract 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 for all abstract members of the interfaces that are listed in the base class list of the class or struct which do not have a reachable implementation; where an implementation can become unreachable due to reabstraction [§19.4.3](interfaces.md#1943-interface-methods). The process of locating implementations of interface members in an implementing class or struct is known as ***interface mapping***.
Copy link
Contributor Author

@Nigel-Ecma Nigel-Ecma Nov 20, 2025

Choose a reason for hiding this comment

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

As @BillWagner observed my first attempt to improve this didn’t cover reabstraction. Wordsmithing this in was a challenge, the reabstraction could be said to “hide” the existing implementation – but I don’t think we want to use word here. I settled on “(un)reachable” but maybe someone can do better? (@RexJaeschke?)

Same change made to line 1466 below

Copy link
Member

Choose a reason for hiding this comment

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

I like it.

Copy link
Member

Choose a reason for hiding this comment

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

I like this, and I'll approve. I'd like @RexJaeschke to weigh in as well.


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, interface, or struct `S`, starting with `C` and repeating for each successive base class and implemented interface of `C`, until a match is located:

Expand Down Expand Up @@ -1463,7 +1463,7 @@ When a class implements an interface, it implicitly also implements all that int

### 19.6.8 Abstract classes and interfaces

Like a non-abstract class, an abstract class shall provide implementations of all abstract 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 for all abstract members of the interfaces that are listed in the base class list of the class or struct which do not have a reachable implementation; where an implementation can become unreachable due to reabstraction [§19.4.3](interfaces.md#1943-interface-methods). However, an abstract class is permitted to map interface methods onto abstract methods.

> *Example*:
>
Expand All @@ -1479,7 +1479,7 @@ Like a non-abstract class, an abstract class shall provide implementations of al
> {
> public abstract void F();
> public abstract void G();
> }
> }
> ```
>
> Here, the implementation of `IMethods` maps `F` and `G` onto abstract methods, which shall be overridden in non-abstract classes that derive from `C`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Sample: Expanded Interfaces

Simple test to check that interfaces can now declare more kinds of members and contain
implementations.

The grammar for all interface members now uses the same productions as for classes,
with any differences being handled in prose, as such this test does not test
these differences.

Note: No Antlr custom predicates have currently been developed for any interface
semantic rules as they are not key to parsing.
Loading
Loading