Skip to content
Merged
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
16 changes: 10 additions & 6 deletions .openpublishing.redirection.csharp.json
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,6 @@
"source_path_from_root": "/docs/csharp/getting-started/testing-library-with-visual-studio.md",
"redirect_url": "/dotnet/core/tutorials/testing-library-with-visual-studio"
},
{
"source_path_from_root": "/docs/csharp/getting-started/whats-new.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-11"
},
{
"source_path_from_root": "/docs/csharp/getting-started/with-visual-studio-2017.md",
"redirect_url": "/dotnet/core/tutorials/with-visual-studio",
Expand Down Expand Up @@ -4753,7 +4749,11 @@
},
{
"source_path_from_root": "/docs/csharp/whats-new/tutorials/static-abstract-interface-methods.md",
"redirect_url": "/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members"
"redirect_url": "/dotnet/advanced-topics/interface-implementation/static-virtual-interface-members"
},
{
"source_path_from_root": "/docs/csharp/whats-new/tutorials/static-virtual-interface-members.md",
"redirect_url": "/dotnet/advanced-topics/interface-implementation/static-virtual-interface-members"
},
{
"source_path_from_root": "/docs/csharp/whats-new/tutorials/top-level-statements.md",
Expand Down Expand Up @@ -5004,9 +5004,13 @@
"source_path_from_root": "/docs/csharp/whats-new/csharp-10.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-version-history#c-version-10"
},
{
"source_path_from_root": "/docs/csharp/whats-new/csharp-11.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-version-history#c-version-11"
},
{
"source_path_from_root": "/docs/csharp/whats-new/index.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-13",
"redirect_url": "/dotnet/csharp/whats-new/csharp-14",
"ms.custom": "updateeachrelease"
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ N/A

## See also

- [Tutorial: Explore static virtual members in interfaces](../../../../csharp/whats-new/tutorials/static-virtual-interface-members.md)
- [Tutorial: Explore static virtual members in interfaces](../../../../csharp/advanced-topics/interface-implementation/static-virtual-interface-members.md)
2 changes: 1 addition & 1 deletion docs/core/whats-new/dotnet-7.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ For more information, see [What's new in Visual Studio 2022](/visualstudio/ide/w

### C# 11

C# 11 includes support for [generic math](../../standard/generics/math.md), raw string literals, file-scoped types, and other new features. For more information, see [What's new in C# 11](../../csharp/whats-new/csharp-11.md).
C# 11 includes support for [generic math](../../standard/generics/math.md), raw string literals, file-scoped types, and other new features. For more information, see [What's new in C# 11](../../csharp/whats-new/csharp-version-history.md#c-version-11).

### F# 7

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// See https://aka.ms/new-console-template for more information

Console.WriteLine(Utilities.MidPoint(12, 24));
Console.WriteLine(Utilities.MidPoint(12, 24));

// <TestRepeat>
var str = new RepeatSequence();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: Explore static virtual members in C# interfaces
description: This advanced tutorial demonstrates scenarios for operators and other static members in interfaces.
ms.date: 07/08/2022
ms.date: 11/18/2025
ms.subservice: advanced-concepts
---
# Tutorial: Explore C# 11 feature - static virtual members in interfaces
# Tutorial: Explore static virtual members in interfaces

C# 11 and .NET 7 include *static virtual members in interfaces*. This feature enables you to define interfaces that include [overloaded operators](../../language-reference/operators/operator-overloading.md) or other static members. Once you've defined interfaces with static members, you can use those interfaces as [constraints](../../programming-guide/generics/constraints-on-type-parameters.md) to create generic types that use operators or other static methods. Even if you don't create interfaces with overloaded operators, you'll likely benefit from this feature and the generic math classes enabled by the language update.
*Interface static virtual members* enable you to define interfaces that include [overloaded operators](../../language-reference/operators/operator-overloading.md) or other static members. Once you define interfaces with static members, you can use those interfaces as [constraints](../../programming-guide/generics/constraints-on-type-parameters.md) to create generic types that use operators or other static methods. Even if you don't create interfaces with overloaded operators, you likely benefit from this feature and the generic math classes enabled by the language update.

In this tutorial, you'll learn how to:
In this tutorial, you learn how to:

> [!div class="checklist"]
>
Expand Down Expand Up @@ -45,7 +45,7 @@ You can create a structure that creates a string of 'A' characters where each in

:::code language="csharp" source="./snippets/staticinterfaces/RepeatSequence.cs":::

More generally, you can build any algorithm where you might want to define `++` to mean "produce the next value of this type". Using this interface produces clear code and results:
More generally, you can build any algorithm where you might want to define `++` to mean "produce the next value of this type." Using this interface produces clear code and results:

:::code language="csharp" source="./snippets/staticinterfaces/Program.cs" id="TestRepeat":::

Expand All @@ -68,7 +68,7 @@ This small example demonstrates the motivation for this feature. You can use nat

## Generic math

The motivating scenario for allowing static methods, including operators, in interfaces is to support [generic math](../../../standard/generics/math.md) algorithms. The .NET 7 base class library contains interface definitions for many arithmetic operators, and derived interfaces that combine many arithmetic operators in an `INumber<T>` interface. Let's apply those types to build a `Point<T>` record that can use any numeric type for `T`. The point can be moved by some `XOffset` and `YOffset` using the `+` operator.
The motivating scenario for allowing static methods, including operators, in interfaces is to support [generic math](../../../standard/generics/math.md) algorithms. The .NET 7 base class library contains interface definitions for many arithmetic operators, and derived interfaces that combine many arithmetic operators in an `INumber<T>` interface. Let's apply those types to build a `Point<T>` record that can use any numeric type for `T`. You can move the point by some `XOffset` and `YOffset` using the `+` operator.

Start by creating a new Console application, either by using `dotnet new` or Visual Studio.

Expand All @@ -91,7 +91,7 @@ public static Point<T> operator +(Point<T> left, Translation<T> right) =>
left with { X = left.X + right.XOffset, Y = left.Y + right.YOffset };
```

For the previous code to compile, you'll need to declare that `T` supports the `IAdditionOperators<TSelf, TOther, TResult>` interface. That interface includes the `operator +` static method. It declares three type parameters: One for the left operand, one for the right operand, and one for the result. Some types implement `+` for different operand and result types. Add a declaration that the type argument, `T` implements `IAdditionOperators<T, T, T>`:
For the previous code to compile, you need to declare that `T` supports the `IAdditionOperators<TSelf, TOther, TResult>` interface. That interface includes the `operator +` static method. It declares three type parameters: One for the left operand, one for the right operand, and one for the result. Some types implement `+` for different operand and result types. Add a declaration that the type argument, `T` implements `IAdditionOperators<T, T, T>`:

```csharp
public record Point<T>(T X, T Y) where T : IAdditionOperators<T, T, T>
Expand All @@ -103,7 +103,7 @@ After you add that constraint, your `Point<T>` class can use the `+` for its add
public record Translation<T>(T XOffset, T YOffset) where T : IAdditionOperators<T, T, T>;
```

The `IAdditionOperators<T, T, T>` constraint prevents a developer using your class from creating a `Translation` using a type that doesn't meet the constraint for the addition to a point. You've added the necessary constraints to the type parameter for `Translation<T>` and `Point<T>` so this code works. You can test by adding code like the following above the declarations of `Translation` and `Point` in your *Program.cs* file:
The `IAdditionOperators<T, T, T>` constraint prevents a developer using your class from creating a `Translation` using a type that doesn't meet the constraint for the addition to a point. You added the necessary constraints to the type parameter for `Translation<T>` and `Point<T>` so this code works. You can test by adding code like the following above the declarations of `Translation` and `Point` in your *Program.cs* file:

:::code language="csharp" source="./snippets/staticinterfaces/Program.cs" id="TestAddition":::

Expand Down Expand Up @@ -131,26 +131,26 @@ public static Translation<T> AdditiveIdentity =>
new Translation<T>(XOffset: 0, YOffset: 0);
```

The preceding code won't compile, because `0` depends on the type. The answer: Use `IAdditiveIdentity<T>.AdditiveIdentity` for `0`. That change means that your constraints must now include that `T` implements `IAdditiveIdentity<T>`. That results in the following implementation:
The preceding code doesn't compile, because `0` depends on the type. The answer: Use `IAdditiveIdentity<T>.AdditiveIdentity` for `0`. That change means that your constraints must now include that `T` implements `IAdditiveIdentity<T>`. That results in the following implementation:

```csharp
public static Translation<T> AdditiveIdentity =>
new Translation<T>(XOffset: T.AdditiveIdentity, YOffset: T.AdditiveIdentity);
```

Now that you've added that constraint on `Translation<T>`, you need to add the same constraint to `Point<T>`:
Now that you added that constraint on `Translation<T>`, you need to add the same constraint to `Point<T>`:

:::code language="csharp" source="./snippets/staticinterfaces/Point.cs":::

This sample has given you a look at how the interfaces for generic math compose. You learned how to:
This sample gave you a look at how the interfaces for generic math compose. You learned how to:

> [!div class="checklist"]
>
> * Write a method that relied on the `INumber<T>` interface so that method could be used with any numeric type.
> * Build a type that relies on the addition interfaces to implement a type that only supports one mathematical operation.
> That type declares its support for those same interfaces so it can be composed in other ways. The algorithms are written using the most natural syntax of mathematical operators.

Experiment with these features and register feedback. You can use the *Send Feedback* menu item in Visual Studio, or create a new [issue](https://github.com/dotnet/roslyn/issues/new/choose) in the roslyn repository on GitHub. Build generic algorithms that work with any numeric type. Build algorithms using these interfaces where the type argument may only implement a subset of number-like capabilities. Even if you don't build new interfaces that use these capabilities, you can experiment with using them in your algorithms.
Experiment with these features and register feedback. You can use the *Send Feedback* menu item in Visual Studio, or create a new [issue](https://github.com/dotnet/roslyn/issues/new/choose) in the roslyn repository on GitHub. Build generic algorithms that work with any numeric type. Build algorithms using these interfaces where the type argument only implements a subset of number-like capabilities. Even if you don't build new interfaces that use these capabilities, you can experiment with using them in your algorithms.

## See also

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Generics and attributes"
description: Learn about applying attributes to generic types. See code examples and view more available resources.
ms.date: 03/15/2023
ms.date: 11/18/2025
helpviewer_keywords:
- "generics [C#], attributes"
- "attributes [C#], with generics"
Expand Down Expand Up @@ -33,7 +33,7 @@ An attribute that references a generic type parameter causes a compile-time erro
class ClassD<T> { }
```

Beginning with C# 11, a generic type can inherit from <xref:System.Attribute>:
A generic type can inherit from <xref:System.Attribute>:

:::code language="csharp" source="./snippets/conceptual/GenericsAndAttributes.cs" id="GenericAttribute":::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ class ClassC { }
//</ClosedGeneric>

//<GenericAttribute>
public class CustomGenericAttribute<T> : Attribute { } //Requires C# 11
public class CustomGenericAttribute<T> : Attribute { }
//</GenericAttribute>
4 changes: 2 additions & 2 deletions docs/csharp/fundamentals/functional/pattern-matching.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Pattern matching overview
description: "Learn about pattern matching expressions in C#"
ms.date: 01/27/2025
ms.date: 11/18/2025
---

# Pattern matching overview
Expand Down Expand Up @@ -40,7 +40,7 @@ The previous example demonstrates a method dispatch based on the value of an enu

:::code language="csharp" source="snippets/patterns/Simulation.cs" ID="PerformStringOperation":::

The preceding example shows the same algorithm, but uses string values instead of an enum. You would use this scenario if your application responds to text commands instead of a regular data format. Starting with C# 11, you can also use a `Span<char>` or a `ReadOnlySpan<char>`to test for constant string values, as shown in the following sample:
The preceding example shows the same algorithm, but uses string values instead of an enum. You would use this scenario if your application responds to text commands instead of a regular data format. You can also use a `Span<char>` or a `ReadOnlySpan<char>`to test for constant string values, as shown in the following sample:

:::code language="csharp" source="snippets/patterns/Simulation.cs" ID="PerformSpanOperation":::

Expand Down
Loading