Skip to content

Commit b747669

Browse files
authored
Miscellaneous bug fixes (dotnet#41967)
* Fixes dotnet#41491 Clarified the diamond problem with default interface methods. Add an image to illustrate the problem, and provide additional text explanation. * Fixes dotnet#40808 Remove the (now) obsolete paragraph. * Fixes dotnet#41507 Clarify how extra braces are processed in interpolated raw string literals. * Fixes dotnet#41538 Add collection expressions to the member access article. Include links to the collection expressions article. * Fixes dotnet#30876 Add important note that an instance constructor called from a static field initializer in the same type that invokes an instance constructor means the instance constructor is called before the static constructor. * Fixes dotnet#41629 Note that the order of static constructor execution isn't specified. Perform a final edit pass. * build fix * Update docs/csharp/programming-guide/strings/index.md
1 parent 3f7b125 commit b747669

File tree

7 files changed

+76
-46
lines changed

7 files changed

+76
-46
lines changed
Lines changed: 1 addition & 0 deletions
Loading

docs/csharp/advanced-topics/interface-implementation/mixins-with-default-interface-methods.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
---
22
title: Create mixin types using default interface methods
33
description: Using default interface members you can extend interfaces with optional default implementations for implementors.
4-
ms.date: 03/17/2023
4+
ms.date: 07/31/2024
55
---
66
# Tutorial: Mix functionality in when creating classes using interfaces with default interface methods
77

88
You can define an implementation when you declare a member of an interface. This feature provides new capabilities where you can define default implementations for features declared in interfaces. Classes can pick when to override functionality, when to use the default functionality, and when not to declare support for discrete features.
99

10-
In this tutorial, you'll learn how to:
10+
In this tutorial, you learn how to:
1111

1212
> [!div class="checklist"]
1313
>
@@ -27,11 +27,11 @@ Extension methods are resolved at compile time, using the declared type of the v
2727

2828
You can declare the default implementations as interface methods. Then, every class automatically uses the default implementation. Any class that can provide a better implementation can override the interface method definition with a better algorithm. In one sense, this technique sounds similar to how you could use [extension methods](../../programming-guide/classes-and-structs/extension-methods.md).
2929

30-
In this article, you'll learn how default interface implementations enable new scenarios.
30+
In this article, you learn how default interface implementations enable new scenarios.
3131

3232
## Design the application
3333

34-
Consider a home automation application. You probably have many different types of lights and indicators that could be used throughout the house. Every light must support APIs to turn them on and off, and to report the current state. Some lights and indicators may support other features, such as:
34+
Consider a home automation application. You probably have many different types of lights and indicators that could be used throughout the house. Every light must support APIs to turn them on and off, and to report the current state. Some lights and indicators might support other features, such as:
3535

3636
- Turn light on, then turn it off after a timer.
3737
- Blink the light for a period of time.
@@ -68,7 +68,7 @@ The `OverheadLight` class can implement the timer function by declaring support
6868
public class OverheadLight : ITimerLight { }
6969
```
7070

71-
A different light type may support a more sophisticated protocol. It can provide its own implementation for `TurnOnFor`, as shown in the following code:
71+
A different light type might support a more sophisticated protocol. It can provide its own implementation for `TurnOnFor`, as shown in the following code:
7272

7373
:::code language="csharp" source="./snippets/mixins-with-default-interface-methods/HalogenLight.cs" id="SnippetHalogenLight":::
7474

@@ -96,7 +96,7 @@ The `HalogenLight` you created earlier doesn't support blinking. So, don't add t
9696

9797
## Detect the light types using pattern matching
9898

99-
Next, let's write some test code. You can make use of C#'s [pattern matching](../../fundamentals/functional/pattern-matching.md) feature to determine a light's capabilities by examining which interfaces it supports. The following method exercises the supported capabilities of each light:
99+
Next, let's write some test code. You can make use of C#'s [pattern matching](../../fundamentals/functional/pattern-matching.md) feature to determine a light's capabilities by examining which interfaces it supports. The following method exercises the supported capabilities of each light:
100100

101101
:::code language="csharp" source="./snippets/mixins-with-default-interface-methods/Program.cs" id="SnippetTestLightFunctions":::
102102

@@ -116,6 +116,12 @@ The default implementation assumes no power:
116116

117117
These changes compile cleanly, even though the `ExtraFancyLight` declares support for the `ILight` interface and both derived interfaces, `ITimerLight` and `IBlinkingLight`. There's only one "closest" implementation declared in the `ILight` interface. Any class that declared an override would become the one "closest" implementation. You saw examples in the preceding classes that overrode the members of other derived interfaces.
118118

119-
Avoid overriding the same method in multiple derived interfaces. Doing so creates an ambiguous method call whenever a class implements both derived interfaces. The compiler can't pick a single better method so it issues an error. For example, if both the `IBlinkingLight` and `ITimerLight` implemented an override of `PowerStatus`, the `OverheadLight` would need to provide a more specific override. Otherwise, the compiler can't pick between the implementations in the two derived interfaces. You can usually avoid this situation by keeping interface definitions small and focused on one feature. In this scenario, each capability of a light is its own interface; only classes inherit multiple interfaces.
119+
Avoid overriding the same method in multiple derived interfaces. Doing so creates an ambiguous method call whenever a class implements both derived interfaces. The compiler can't pick a single better method so it issues an error. For example, if both the `IBlinkingLight` and `ITimerLight` implemented an override of `PowerStatus`, the `OverheadLight` would need to provide a more specific override. Otherwise, the compiler can't pick between the implementations in the two derived interfaces. This situation is shown in the following diagram:
120120

121-
This sample shows one scenario where you can define discrete features that can be mixed into classes. You declare any set of supported functionality by declaring which interfaces a class supports. The use of virtual default interface methods enables classes to use or define a different implementation for any or all the interface methods. This language capability provides new ways to model the real-world systems you're building. Default interface methods provide a clearer way to express related classes that may mix and match different features using virtual implementations of those capabilities.
121+
:::image type="content" source="./media/mixins-with-default-interface-methods/diamond-problem.svg" alt-text="illustration of the diamond problem with default interface methods":::
122+
123+
The preceding diagram illustrates the ambiguity. `OverheadLight` doesn't provide an implementation of `ILight.PowerStatus`. Both `IBlinkingLight` and `ITimerLight` provide overrides that are more specific. A call to `ILight.PowerStatus` on an instance of `OverheadLight` is ambiguous. You must add a new override in `OverheadLight` to resolve the ambiguity.
124+
125+
You can usually avoid this situation by keeping interface definitions small and focused on one feature. In this scenario, each capability of a light is its own interface; only classes inherit multiple interfaces.
126+
127+
This sample shows one scenario where you can define discrete features that can be mixed into classes. You declare any set of supported functionality by declaring which interfaces a class supports. The use of virtual default interface methods enables classes to use or define a different implementation for any or all the interface methods. This language capability provides new ways to model the real-world systems you're building. Default interface methods provide a clearer way to express related classes that might mix and match different features using virtual implementations of those capabilities.

0 commit comments

Comments
 (0)