Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Download Microsoft EdgeMore info about Internet Explorer and Microsoft Edge
Table of contentsExit focus mode

What's new in C# 11

  • 2024-03-15
Feedback

In this article

The following features were added in C# 11:

C# 11 is supported on.NET 7. For more information, seeC# language versioning.

You can download the latest .NET 7 SDK from the.NET downloads page. You can also downloadVisual Studio 2022, which includes the .NET 7 SDK.

Note

We're interested in your feedback on these features. If you find issues with any of these new features, create anew issue in thedotnet/roslyn repository.

Generic attributes

You can declare ageneric class whose base class isSystem.Attribute. This feature provides a more convenient syntax for attributes that require aSystem.Type parameter. Previously, you'd need to create an attribute that takes aType as its constructor parameter:

// Before C# 11:public class TypeAttribute : Attribute{   public TypeAttribute(Type t) => ParamType = t;   public Type ParamType { get; }}

And to apply the attribute, you use thetypeof operator:

[TypeAttribute(typeof(string))]public string Method() => default;

Using this new feature, you can create a generic attribute instead:

// C# 11 feature:public class GenericAttribute<T> : Attribute { }

Then, specify the type parameter to use the attribute:

[GenericAttribute<string>()]public string Method() => default;

You must supply all type parameters when you apply the attribute. In other words, the generic type must befully constructed.In the example above, the empty parentheses (( and)) can be omitted as the attribute does not have any arguments.

public class GenericType<T>{   [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.   public string Method() => default;}

The type arguments must satisfy the same restrictions as thetypeof operator. Types that require metadata annotations aren't allowed. For example, the following types aren't allowed as the type parameter:

  • dynamic
  • string? (or any nullable reference type)
  • (int X, int Y) (or any other tuple types using C# tuple syntax).

These types aren't directly represented in metadata. They include annotations that describe the type. In all cases, you can use the underlying type instead:

  • object fordynamic.
  • string instead ofstring?.
  • ValueTuple<int, int> instead of(int X, int Y).

Generic math support

There are several language features that enable generic math support:

  • static virtual members in interfaces
  • checked user defined operators
  • relaxed shift operators
  • unsigned right-shift operator

You can addstatic abstract orstatic virtual members in interfaces to define interfaces that include overloadable operators, other static members, and static properties. The primary scenario for this feature is to use mathematical operators in generic types. For example, you can implement theSystem.IAdditionOperators<TSelf, TOther, TResult> interface in a type that implementsoperator +. Other interfaces define other mathematical operations or well-defined values. You can learn about the new syntax in the article oninterfaces. Interfaces that includestatic virtual methods are typicallygeneric interfaces. Furthermore, most will declare a constraint that the type parameterimplements the declared interface.

You can learn more and try the feature yourself in the tutorialExplore static abstract interface members, or thePreview features in .NET 6 – generic math blog post.

Generic math created other requirements on the language.

  • unsigned right shift operator: Before C# 11, to force an unsigned right-shift, you would need to cast any signed integer type to an unsigned type, perform the shift, then cast the result back to a signed type. Beginning in C# 11, you can use the>>>, theunsigned shift operator.
  • relaxed shift operator requirements: C# 11 removes the requirement that the second operand must be anint or implicitly convertible toint. This change allows types that implement generic math interfaces to be used in these locations.
  • checked and unchecked user defined operators: Developers can now definechecked andunchecked arithmetic operators. The compiler generates calls to the correct variant based on the current context. You can read more aboutchecked operators in the article onArithmetic operators.

NumericIntPtr andUIntPtr

Thenint andnuint types now aliasSystem.IntPtr andSystem.UIntPtr, respectively.

Newlines in string interpolations

The text inside the{ and} characters for a string interpolation can now span multiple lines. The text between the{ and} markers is parsed as C#. Any legal C#, including newlines, is allowed. This feature makes it easier to read string interpolations that use longer C# expressions, like pattern matchingswitch expressions, or LINQ queries.

You can learn more about the newlines feature in thestring interpolations article in the language reference.

List patterns

List patterns extend pattern matching to match sequences of elements in a list or an array. For example,sequence is [1, 2, 3] istrue when thesequence is an array or a list of three integers (1, 2, and 3). You can match elements using any pattern, including constant, type, property and relational patterns. The discard pattern (_) matches any single element, and the newrange pattern (..) matches any sequence of zero or more elements.

You can learn more details about list patterns in thepattern matching article in the language reference.

Improved method group conversion to delegate

The C# standard onMethod group conversions now includes the following item:

  • The conversion is permitted (but not required) to use an existing delegate instance that already contains these references.

Previous versions of the standard prohibited the compiler from reusing the delegate object created for a method group conversion. The C# 11 compiler caches the delegate object created from a method group conversion and reuses that single delegate object. This feature was first available in Visual Studio 2022 version 17.2 as a preview feature, and in .NET 7 Preview 2.

Raw string literals

Raw string literals are a new format for string literals. Raw string literals can contain arbitrary text, including whitespace, new lines, embedded quotes, and other special characters without requiring escape sequences. A raw string literal starts with at least three double-quote (""") characters. It ends with the same number of double-quote characters. Typically, a raw string literal uses three double quotes on a single line to start the string, and three double quotes on a separate line to end the string. The newlines following the opening quote and preceding the closing quote aren't included in the final content:

string longMessage = """    This is a long message.    It has several lines.        Some are indented                more than others.    Some should start at the first column.    Some have "quoted text" in them.    """;

Any whitespace to the left of the closing double quotes will be removed from the string literal. Raw string literals can be combined with string interpolation to include braces in the output text. Multiple$ characters denote how many consecutive braces start and end the interpolation:

var location = $$"""   You are at {{{Longitude}}, {{Latitude}}}   """;

The preceding example specifies that two braces start and end an interpolation. The third repeated opening and closing brace are included in the output string.

You can learn more about raw string literals in the article onstrings in the programming guide, and the language reference articles onstring literals andinterpolated strings.

Auto-default struct

The C# 11 compiler ensures that all fields of astruct type are initialized to their default value as part of executing a constructor. This change means any field or auto property not initialized by a constructor is automatically initialized by the compiler. Structs where the constructor doesn't definitely assign all fields now compile, and any fields not explicitly initialized are set to their default value. You can read more about how this change affects struct initialization in the article onstructs.

Pattern matchSpan<char> orReadOnlySpan<char> on a constantstring

You've been able to test if astring had a specific constant value using pattern matching for several releases. Now, you can use the same pattern matching logic with variables that areSpan<char> orReadOnlySpan<char>.

Extended nameof scope

Type parameter names and parameter names are now in scope when used in anameof expression in anattribute declaration on that method. This feature means you can use thenameof operator to specify the name of a method parameter in an attribute on the method or parameter declaration. This feature is most often useful to add attributes fornullable analysis.

UTF-8 string literals

You can specify theu8 suffix on a string literal to specify UTF-8 character encoding. If your application needs UTF-8 strings, for HTTP string constants or similar text protocols, you can use this feature to simplify the creation of UTF-8 strings.

You can learn more about UTF-8 string literals in the string literal section of the article onbuiltin reference types.

Required members

You can add therequired modifier to properties and fields to enforce constructors and callers to initialize those values. TheSystem.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute can be added to constructors to inform the compiler that a constructor initializesall required members.

For more information on required members, See theRequired properties section of the properties article.

ref fields andref scoped variables

You can declareref fields inside aref struct. This supports types such asSystem.Span<T> without special attributes or hidden internal types.

You can add thescoped modifier to anyref declaration. This limits thescope where the reference can escape to.

File local types

Beginning in C# 11, you can use thefile access modifier to create a type whose visibility is scoped to the source file in which it is declared. This feature helps source generator authors avoid naming collisions. You can learn more about this feature in the article onfile-scoped types in the language reference.

See also

Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, seeour contributor guide.

Feedback

Was this page helpful?

YesNo

In this article

Was this page helpful?

YesNo