-
Notifications
You must be signed in to change notification settings - Fork 6k
Don't disallow adding a DIM to an interface #48801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -9,47 +9,50 @@ helpviewer_keywords: | |||||
--- | ||||||
# :::no-loc text="interface"::: (C# Reference) | ||||||
|
||||||
An interface defines a contract. Any [`class`](class.md), [`record`](../builtin-types/record.md) or [`struct`](../builtin-types/struct.md) that implements that contract must provide an implementation of the members defined in the interface. An interface may define a default implementation for members. It may also define [`static`](static.md) members in order to provide a single implementation for common functionality. Beginning with C# 11, an interface may define `static abstract` or `static virtual` members to declare that an implementing type must provide the declared members. Typically, `static virtual` methods declare that an implementation must define a set of [overloaded operators](../operators/operator-overloading.md). | ||||||
An interface defines a contract. Any [`class`](class.md), [`record`](../builtin-types/record.md) or [`struct`](../builtin-types/struct.md) that implements that contract must provide an implementation of the members defined in the interface. | ||||||
|
||||||
An interface can define a [default implementation](#default-interface-members) for a member. It can also define [`static`](static.md) members to provide a single implementation for common functionality. | ||||||
|
||||||
Beginning with C# 11, an interface can define `static abstract` or `static virtual` members to declare that an implementing type must provide the declared members. Typically, `static virtual` methods declare that an implementation must define a set of [overloaded operators](../operators/operator-overloading.md). | ||||||
|
||||||
In the following example, class `ImplementationClass` must implement a method named `SampleMethod` that has no parameters and returns `void`. | ||||||
|
||||||
[!code-csharp[csrefKeywordsTypes#14](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs#14)] | ||||||
|
||||||
For more information and examples, see [Interfaces](../../fundamentals/types/interfaces.md). | ||||||
|
||||||
A top-level interface, one declared in a namespace but not nested inside another type, can be declared `public` or `internal`. The default is `internal`. Nested interface declarations, those declared inside another type, can be declared using any access modifier. | ||||||
## Access modifiers | ||||||
|
||||||
Interface members without an implementation can't include an access modifier. Members with a default implementation can include any access modifier. | ||||||
An interface can be a member of a namespace or a class. A top-level interface, one declared in a namespace but not nested inside another type, can be declared `public` or `internal`. The default is `internal`. Nested interface declarations, those declared inside another type, can be declared using any access modifier. | ||||||
|
||||||
## Example interface | ||||||
Interface members without an implementation can't include an access modifier. Members with a default implementation can include any access modifier. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is no longer true. Let's change it:
Suggested change
|
||||||
|
||||||
[!code-csharp[csrefKeywordsTypes#14](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csrefKeywordsTypes/CS/keywordsTypes.cs#14)] | ||||||
## Interface members | ||||||
|
||||||
An interface can be a member of a namespace or a class. An interface declaration can contain declarations (signatures without any implementation) of the following members: | ||||||
An interface declaration can contain the following members: | ||||||
|
||||||
- [Methods](../../programming-guide/classes-and-structs/methods.md) | ||||||
- [Properties](../../programming-guide/classes-and-structs/using-properties.md) | ||||||
- [Indexers](../../programming-guide/indexers/using-indexers.md) | ||||||
- [Events](event.md) | ||||||
- [Methods](../../programming-guide/classes-and-structs/methods.md). | ||||||
- [Properties](../../programming-guide/classes-and-structs/using-properties.md). | ||||||
- [Indexers](../../programming-guide/indexers/using-indexers.md). | ||||||
- [Events](event.md). | ||||||
- [Constants](const.md). | ||||||
- [Operators](../operators/operator-overloading.md). | ||||||
- [A static constructor](../../programming-guide/classes-and-structs/constructors.md#static-constructors). | ||||||
- [Nested types](../../programming-guide/classes-and-structs/nested-types.md). | ||||||
- [Static fields, methods, properties, indexers, and events](static.md). | ||||||
- [Member declarations using the explicit interface implementation syntax](~/_csharplang/proposals/csharp-8.0/default-interface-methods.md#explicit-implementation-in-interfaces). | ||||||
- Explicit access modifiers (the default access is [`public`](access-modifiers.md)). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add clarifying comment:
Suggested change
|
||||||
|
||||||
## Default interface members | ||||||
|
||||||
These preceding member declarations typically don't contain a body. An interface member may declare a body. Member bodies in an interface are the *default implementation*. Members with bodies permit the interface to provide a "default" implementation for classes and structs that don't provide an overriding implementation. | ||||||
Member declarations typically don't contain a body, however, an interface member can declare a body. Member bodies in an interface are the *default implementation*. Members with bodies permit the interface to provide a "default" implementation for classes and structs that don't provide an overriding implementation. | ||||||
|
||||||
> [!IMPORTANT] | ||||||
> Adding default interfaces members forces any `ref struct` that implements the interface to add an explicit declaration of that member. | ||||||
|
||||||
An interface may include: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list got orphaned at some point. |
||||||
|
||||||
- [Constants](const.md) | ||||||
- [Operators](../operators/operator-overloading.md) | ||||||
- [Static constructor](../../programming-guide/classes-and-structs/constructors.md#static-constructors). | ||||||
- [Nested types](../../programming-guide/classes-and-structs/nested-types.md) | ||||||
- [Static fields, methods, properties, indexers, and events](static.md) | ||||||
- [Member declarations using the explicit interface implementation syntax](~/_csharplang/proposals/csharp-8.0/default-interface-methods.md#explicit-implementation-in-interfaces). | ||||||
- Explicit access modifiers (the default access is [`public`](access-modifiers.md)). | ||||||
|
||||||
## Static abstract and virtual members | ||||||
|
||||||
Beginning with C# 11, an interface may declare `static abstract` and `static virtual` members for all member types except fields. Interfaces can declare that implementing types must define operators or other static members. This feature enables generic algorithms to specify number-like behavior. You can see examples in the numeric types in the .NET runtime, such as <xref:System.Numerics.INumber%601?displayProperty=nameWithType>. These interfaces define common mathematical operators that are implemented by many numeric types. The compiler must resolve calls to `static virtual` and `static abstract` methods at compile time. The `static virtual` and `static abstract` methods declared in interfaces don't have a runtime dispatch mechanism analogous to `virtual` or `abstract` methods declared in classes. Instead, the compiler uses type information available at compile time. Therefore, `static virtual` methods are almost exclusively declared in [generic interfaces](../../programming-guide/generics/generic-interfaces.md). Furthermore, most interfaces that declare `static virtual` or `static abstract` methods declare that one of the type parameters must [implement the declared interface](../../programming-guide/generics/constraints-on-type-parameters.md#type-arguments-implement-declared-interface). For example, the `INumber<T>` interface declares that `T` must implement `INumber<T>`. The compiler uses the type argument to resolve calls to the methods and operators declared in the interface declaration. For example, the `int` type implements `INumber<int>`. When the type parameter `T` denotes the type argument `int`, the `static` members declared on `int` are invoked. Alternatively, when `double` is the type argument, the `static` members declared on the `double` type are invoked. | ||||||
Beginning with C# 11, an interface can declare `static abstract` and `static virtual` members for all member types except fields. Interfaces can declare that implementing types must define operators or other static members. This feature enables generic algorithms to specify number-like behavior. You can see examples in the numeric types in the .NET runtime, such as <xref:System.Numerics.INumber%601?displayProperty=nameWithType>. These interfaces define common mathematical operators that are implemented by many numeric types. The compiler must resolve calls to `static virtual` and `static abstract` methods at compile time. The `static virtual` and `static abstract` methods declared in interfaces don't have a runtime dispatch mechanism analogous to `virtual` or `abstract` methods declared in classes. Instead, the compiler uses type information available at compile time. Therefore, `static virtual` methods are almost exclusively declared in [generic interfaces](../../programming-guide/generics/generic-interfaces.md). Furthermore, most interfaces that declare `static virtual` or `static abstract` methods declare that one of the type parameters must [implement the declared interface](../../programming-guide/generics/constraints-on-type-parameters.md#type-arguments-implement-declared-interface). For example, the `INumber<T>` interface declares that `T` must implement `INumber<T>`. The compiler uses the type argument to resolve calls to the methods and operators declared in the interface declaration. For example, the `int` type implements `INumber<int>`. When the type parameter `T` denotes the type argument `int`, the `static` members declared on `int` are invoked. Alternatively, when `double` is the type argument, the `static` members declared on the `double` type are invoked. | ||||||
BillWagner marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
> [!IMPORTANT] | ||||||
> Method dispatch for `static abstract` and `static virtual` methods declared in interfaces is resolved using the compile time type of an expression. If the runtime type of an expression is derived from a different compile time type, the static methods on the base (compile time) type will be called. | ||||||
|
@@ -58,7 +61,7 @@ You can try this feature by working with the tutorial on [static abstract member | |||||
|
||||||
## Interface inheritance | ||||||
|
||||||
Interfaces may not contain instance state. While static fields are now permitted, instance fields aren't permitted in interfaces. [Instance auto-properties](../../programming-guide/classes-and-structs/auto-implemented-properties.md) aren't supported in interfaces, as they would implicitly declare a hidden field. This rule has a subtle effect on property declarations. In an interface declaration, the following code doesn't declare an automatically implemented property as it does in a `class` or `struct`. Instead, it declares a property that doesn't have a default implementation but must be implemented in any type that implements the interface: | ||||||
Interfaces cannot contain instance state. While static fields are now permitted, instance fields aren't permitted in interfaces. [Instance auto-properties](../../programming-guide/classes-and-structs/auto-implemented-properties.md) aren't supported in interfaces, as they would implicitly declare a hidden field. This rule has a subtle effect on property declarations. In an interface declaration, the following code doesn't declare an automatically implemented property as it does in a `class` or `struct`. Instead, it declares a property that doesn't have a default implementation but must be implemented in any type that implements the interface: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. contraction:
Suggested change
|
||||||
|
||||||
```csharp | ||||||
public interface INamed | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding one more condition: