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 editor mode

What's new in C# 14

Feedback

In this article

C# 14 includes the following new features. You can try these features using the latestVisual Studio 2026 version or the.NET 10 SDK:

C# 14 is the latest C# release. C# 14 is supported on.NET 10. For more information, seeC# language versioning.

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

You can find any breaking changes introduced in C# 14 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.

Extension members

C# 14 adds new syntax to defineextension members. The new syntax enables you to declareextension properties in addition to extension methods. You can also declare extension members that extend the type, rather than an instance of the type. In other words, these new extension members can appear as static members of the type you extend. These extensions can include user defined operators implemented as static extension methods. The following code example shows an example of the different kinds of extension members you can declare:

public static class Enumerable{    // Extension block    extension<TSource>(IEnumerable<TSource> source) // extension members for IEnumerable<TSource>    {        // Extension property:        public bool IsEmpty => !source.Any();        // Extension method:        public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }    }    // extension block, with a receiver type only    extension<TSource>(IEnumerable<TSource>) // static extension members for IEnumerable<Source>    {        // static extension method:        public static IEnumerable<TSource> Combine(IEnumerable<TSource> first, IEnumerable<TSource> second) { ... }        // static extension property:        public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>();        // static user defined operator:        public static IEnumerable<TSource> operator + (IEnumerable<TSource> left, IEnumerable<TSource> right) => left.Concat(right);    }}

The members in the first extension block are called as though they're instance members ofIEnumerable<TSource>, for examplesequence.IsEmpty. The members in the second extension block are called as though they're static members ofIEnumerable<TSource>, for exampleIEnumerable<int>.Identity.

You can learn more details by reading the article onextension members in the programming guide, the language reference article on theextension keyword, and thefeature specification for the new extension members feature.

Thefield keyword

The tokenfield enables you to write a property accessor body without declaring an explicit backing field. The tokenfield is replaced with a compiler synthesized backing field.

For example, previously, if you wanted to ensure that astring property couldn't be set tonull, you had to declare a backing field and implement both accessors:

private string _msg;public string Message{    get => _msg;    set => _msg = value ?? throw new ArgumentNullException(nameof(value));}

You can now simplify your code to:

public string Message{    get;    set => field = value ?? throw new ArgumentNullException(nameof(value));}

You can declare a body for one or both accessors for a field backed property.

There's a potential breaking change or confusion reading code in types that also include a symbol namedfield. You can use@field orthis.field to disambiguate between thefield keyword and the identifier, or you can rename the currentfield symbol to provide better distinction.

Implicit span conversions

C# 14 introduces first-class support forSystem.Span<T> andSystem.ReadOnlySpan<T> in the language. This support involves new implicit conversions allowing more natural programming with these types.

Span<T> andReadOnlySpan<T> are used in many key ways in C# and the runtime. Their introduction improves performance without risking safety. C# 14 recognizes the relationship and supports some conversions betweenReadOnlySpan<T>,Span<T>, andT[]. The span types can be extension method receivers, compose with other conversions, and help with generic type inference scenarios.

You can find the list of implicit span conversions in the article onbuilt-in types in the language reference section. You can learn more details by reading the feature specification forFirst class span types.

Unbound generic types andnameof

Beginning with C# 14, the argument tonameof can be an unbound generic type. For example,nameof(List<>) evaluates toList. In earlier versions of C#, only closed generic types, such asList<int>, could be used to return theList name.

Simple lambda parameters with modifiers

You can add parameter modifiers, such asscoped,ref,in,out, orref readonly to lambda expression parameters without specifying the parameter type:

delegate bool TryParse<T>(string text, out T result);// ...TryParse<int> parse1 = (text, out result) => Int32.TryParse(text, out result);

Previously, adding any modifiers was allowed only when the parameter declarations included the types for the parameters. The preceding declaration would require types on all parameters:

TryParse<int> parse2 = (string text, out int result) => Int32.TryParse(text, out result);

Theparams modifier still requires an explicitly typed parameter list.

You can read more about these changes in the article onlambda expressions in the C# language reference.

More partial members

You can now declareinstance constructors andevents aspartial members.

Partial constructors and partial events must include exactly onedefining declaration and oneimplementing declaration.

Only the implementing declaration of a partial constructor can include a constructor initializer:this() orbase(). Only one partial type declaration can include the primary constructor syntax.

The implementing declaration of a partial event must includeadd andremove accessors. The defining declaration declares a field-like event.

User defined compound assignment

You can learn more in the feature specification foruser-defined compound assignment.

Null-conditional assignment

The null-conditional member access operators,?. and?[], can now be used on the left hand side of an assignment or compound assignment.

Before C# 14, you needed to null-check a variable before assigning to a property:

if (customer is not null){    customer.Order = GetCurrentOrder();}

You can simplify the preceding code using the?. operator:

customer?.Order = GetCurrentOrder();

The right side of the= operator is evaluated only when the left side isn't null. Ifcustomer is null, the code doesn't callGetCurrentOrder.

In addition to assignment, you can use null-conditional member access operators with compound assignment operators (+=,-=, and others). However, increment and decrement,++ and--, aren't allowed.

You can learn more in the language reference article on theconditional member access and the feature specification fornull-conditional assignment.

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?

YesNoNo

Need help with this topic?

Want to try using Ask Learn to clarify or guide you through this topic?

Suggest a fix?

  • Last updated on

In this article

Was this page helpful?

YesNo
NoNeed help with this topic?

Want to try using Ask Learn to clarify or guide you through this topic?

Suggest a fix?