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# 13

  • 2025-05-29
Feedback

In this article

C# 13 includes the following new features. You can try these features using the latestVisual Studio 2022 version or the.NET 9 SDK:

Beginning with Visual Studio 17.12, C# 13 includes thefield contextual keyword as a preview feature.

C# 13 is supported on.NET 9. For more information, seeC# language versioning.

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

You can find any breaking changes introduced in C# 13 in our article onbreaking changes.

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.

params collections

Theparams modifier isn't limited to array types. You can now useparams with any recognized collection type, includingSystem.Span<T>,System.ReadOnlySpan<T>, and types that implementSystem.Collections.Generic.IEnumerable<T> and have anAdd method. In addition to concrete types, the interfacesSystem.Collections.Generic.IEnumerable<T>,System.Collections.Generic.IReadOnlyCollection<T>,System.Collections.Generic.IReadOnlyList<T>,System.Collections.Generic.ICollection<T>, andSystem.Collections.Generic.IList<T> can also be used.

When an interface type is used, the compiler synthesizes the storage for the arguments supplied. You can learn more in the feature specification forparams collections.

For example, method declarations can declare spans asparams parameters:

public void Concat<T>(params ReadOnlySpan<T> items){    for (int i = 0; i < items.Length; i++)    {        Console.Write(items[i]);        Console.Write(" ");    }    Console.WriteLine();}

New lock object

The .NET 9 runtime includes a new type for thread synchronization, theSystem.Threading.Lock type. This type provides better thread synchronization through its API. TheLock.EnterScope() method enters an exclusive scope. Theref struct returned from that supports theDispose() pattern to exit the exclusive scope.

The C#lock statement recognizes if the target of the lock is aLock object. If so, it uses the updated API, rather than the traditional API usingSystem.Threading.Monitor. The compiler also recognizes if you convert aLock object to another type and theMonitor based code would be generated. You can read more in the feature specification for thenew lock object.

This feature allows you to get the benefits of the new library type by changing the type of object youlock. No other code needs to change.

New escape sequence

You can use\e as acharacter literal escape sequence for theESCAPE character, UnicodeU+001B. Previously, you used\u001b or\x1b. Using\x1b wasn't recommended because if the next characters following1b were valid hexadecimal digits, those characters became part of the escape sequence.

Method group natural type

This feature makes small optimizations to overload resolution involving method groups. Amethod group is a method and all overloads with the same name. The previous behavior was for the compiler to construct the full set of candidate methods for a method group. If a natural type was needed, the natural type was determined from the full set of candidate methods.

The new behavior is to prune the set of candidate methods at each scope, removing those candidate methods that aren't applicable. Typically, the removed methods are generic methods with the wrong arity, or constraints that aren't satisfied. The process continues to the next outer scope only if no candidate methods are found. This process more closely follows the general algorithm for overload resolution. If all candidate methods found at a given scope don't match, the method group doesn't have a natural type.

You can read the details of the changes in theproposal specification.

Implicit index access

The implicit "from the end" index operator,^, is now allowed in an object initializer expression for single-dimension collections. For example, you can now initialize a single-dimension array using an object initializer as shown in the following code:

public class TimerRemaining{    public int[] buffer { get; set; } = new int[10];}var countdown = new TimerRemaining(){    buffer =    {        [^1] = 0,        [^2] = 1,        [^3] = 2,        [^4] = 3,        [^5] = 4,        [^6] = 5,        [^7] = 6,        [^8] = 7,        [^9] = 8,        [^10] = 9    }};

TheTimerRemaining class includes abuffer array initialized to a length of 10. The preceding example assigns values to this array using the "from the end" index operator (^), effectively creating an array that counts down from 9 to 0.

In versions before C# 13, the^ operator can't be used in an object initializer. You need to index the elements from the front.

ref andunsafe in iterators andasync methods

This feature and the following two features enableref struct types to use new constructs. You won't use these features unless you write your ownref struct types. More likely, you'll see an indirect benefit asSystem.Span<T> andSystem.ReadOnlySpan<T> gain more functionality.

Before C# 13, iterator methods (methods that useyield return) andasync methods couldn't declare localref variables, nor could they have anunsafe context.

In C# 13,async methods can declareref local variables, or local variables of aref struct type. However, those variables can't be accessed across anawait boundary. Neither can they be accessed across ayield return boundary.

This relaxed restriction enables the compiler to allow verifiably safe use ofref local variables andref struct types in more places. You can safely use types likeSystem.ReadOnlySpan<T> in these methods. The compiler tells you if you violate safety rules.

In the same fashion, C# 13 allowsunsafe contexts in iterator methods. However, allyield return andyield break statements must be in safe contexts.

allows ref struct

Before C# 13,ref struct types couldn't be declared as the type argument for a generic type or method. Now, generic type declarations can add an anti-constraint,allows ref struct. This anti-constraint declares that the type argument supplied for that type parameter can be aref struct type. The compiler enforces ref safety rules on all instances of that type parameter.

For example, you might declare a generic type like the following code:

public class C<T> where T : allows ref struct{    // Use T as a ref struct:    public void M(scoped T p)    {        // The parameter p must follow ref safety rules    }}

This enables types such asSystem.Span<T> andSystem.ReadOnlySpan<T> to be used with generic algorithms, where applicable. You can learn more in the updates forwhere and the programming guide article ongeneric constraints.

ref struct interfaces

Before C# 13,ref struct types weren't allowed to implement interfaces. Beginning with C# 13, they can. You can declare that aref struct type implements an interface. However, to ensure ref safety rules, aref struct type can't be converted to an interface type. That conversion is a boxing conversion, and could violate ref safety. Explicit interface method declarations in aref struct can be accessed only through a type parameter where that type parameterallows ref struct. Also,ref struct types must implement all methods declared in an interface, including those methods with a default implementation.

Learn more in the updates onref struct types and the addition of theallows ref struct generic constraint.

More partial members

You can declarepartial properties andpartial indexers in C# 13. Partial properties and indexers generally follow the same rules aspartial methods: you create onedeclaring declaration and oneimplementing declaration. The signatures of the two declarations must match. One restriction is that you can't use an auto-property declaration forimplementing a partial property. Properties that don't declare a body are considered thedeclaring declaration.

public partial class C{    // Declaring declaration    public partial string Name { get; set; }}public partial class C{    // implementation declaration:    private string _name;    public partial string Name    {        get => _name;        set => _name = value;    }}

You can learn more in the article onpartial members.

Overload resolution priority

In C# 13, the compiler recognizes theOverloadResolutionPriorityAttribute to prefer one overload over another. Library authors can use this attribute to ensure that a new, better overload is preferred over an existing overload. For example, you might add a new overload that's more performant. You don't want to break existing code that uses your library, but you want users to update to the new version when they recompile. You can useOverload resolution priority to inform the compiler which overload should be preferred. Overloads with the highest priority are preferred.

This feature is intended for library authors to avoid ambiguity when adding new overloads. Library authors should use care with this attribute to avoid confusion.

Thefield keyword

Thefield contextual keyword is in C# 13 as a preview feature. The tokenfield accesses the compiler synthesized backing field in a property accessor. It enables you to write an accessor body without declaring an explicit backing field in your type declaration. You can declare a body for one or both accessors for a field backed property.

Thefield feature is released as a preview feature. We want to learn from your experiences using it. There's a potential breaking change or confusion reading code in types that also include a field namedfield. You can use@field orthis.field to disambiguate between thefield keyword and the identifier.

Important

Thefield keyword is a preview feature in C# 13. You must be using .NET 9 and set your<LangVersion> element topreview in your project file in order to use thefield contextual keyword.

You should be careful using thefield keyword feature in a class that has a field namedfield. The newfield keyword shadows a field namedfield in the scope of a property accessor. You can either change the name of thefield variable, or use the@ token to reference thefield identifier as@field. You can learn more by reading the feature specification forthefield keyword.

If you try this feature and have feedback, add it to thefeature issue in thecsharplang repository.

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