blog post

New Features in C# 13

Sponsors of the Blog Post

Master The Clean Architecture. This comprehensive course will teach you how to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. Join 3,600+ students to accelerate your growth as a software architect.

Learn more

Master The Modular Monolith Architecture. This in-depth course will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario. Join 1,600+ students to accelerate your growth as a software architect.

Learn more

.NET 9 and C# 13 were released on November 12, 2024. In this blog post, I want to show you a list of new features in C# 13.

1. Params Collections

Previously, when using params keyword you were able to use only arrays:

csharp
PrintNumbers(1, 2, 3, 4, 5); public void PrintNumbers(params int[] numbers) { // ... }

C# 13 introduces Params Collections, allowing you to use the following concrete types:

  • Arrays
  • IEnumerable<T>
  • List<T>
  • Span<T>

For example, you can use a list:

csharp
List<int>numbers = [ 1, 2, 3, 4, 5 ]; PrintNumbers(numbers); public void PrintNumbers(params List<int> numbers) { // ... }

And further in PrintNumbers method you can use, for example, LINQ methods over the params collection.

2. New Lock Object

System.Threading.Lock is a new thread synchronization type in .NET 9 runtime. It offers better and faster thread synchronization through the API.

How it works:

  • Lock.EnterScope() method enters an exclusive scope and returns a ref struct.
  • Dispose method exits the exclusive scope

When you replace object with a new Lock type inside a lock statement, it starts using a new thread synchronization API. Rather than using old API through System.Threading.Monitor.

csharp
public class LockClass { private readonly System.Threading.Lock _lockObj = new(); public void Do(int i) { lock (_lockObj) { Console.WriteLine($"Do work: {i}"); } } }

3. Partial Properties and Indexers

C# 13 adds support for partial Properties and Indexers. Partial Properties and Indexers let you split the logic for getters, setters, and index accessors across multiple files.

This feature can be useful particularly for source generators.

csharp
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; } }

4. Overload Resolution Priority

With Overload Resolution Priority, you can select the exact order of methods that will be shown in the code editor suggestions.

csharp
using System.Runtime.CompilerServices; public static class MappingExtensions { [OverloadResolutionPriority(1)] public static Product ToResponse(this Product entity, Result result) => new Product(...); [OverloadResolutionPriority(0)] public static Product ToResponse(this Product entity) => new Product(...); }

5. Implicit Index Access

C# 13 now allows using "from the end" index operator (^) in an object initializer expression.

For example, you can now initialize an array that counts down from 4 to 0:

csharp
var countdown = new TimerRemaining() { buffer = { [^1] = 0, [^2] = 1, [^3] = 2, [^4] = 3, [^5] = 4 } };

In previous C# versions, you were not able to use the ^ operator in object initializers.

6. New Escape Sequence

In previous C# versions you needed to use \u001b or \x1b for the ESCAPE character. But this code had potential for collisions with other sequences.

In C# 13 you can use \e as a character for the ESCAPE character.

csharp
var text = "\x1b[1mThis text is bold\x1b[0m"; Console.WriteLine(text); var text = "\e[1mThis text is bold\e[0m"; Console.WriteLine(text);

7. Ref and Unsafe in Iterators and Async Methods

Before C# 13, the following methods couldn't declare local ref variables or have an unsafe context:

  • async methods
  • iterator methods - methods that use yield return

C# 13 removes these restrictions, and you can use Spans (that are ref structs) inside async methods:

csharp
public async Task ProcessTextAsync() { string text = await GetTextAsync(...); ReadOnlySpan<char> span = text; span = span.Slice(2, 10); Console.WriteLine(span.ToString()); }

However, those ref struct and unsafe variables can't be accessed across an await boundary. Neither can they be accessed across a yield return boundary.

8. 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 a ref struct type. The compiler enforces ref safety rules on all instances of that type parameter.

This enables types such as System.Span<T> and System.ReadOnlySpan<T> to be used with generic algorithms, where applicable.

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

9. Ref Struct Interfaces

Starting from C# 13, ref struct can now implement interfaces.

However, to ensure ref safety rules, a ref struct type can't be converted to an interface type. That conversion is a boxing conversion, and could violate ref safety. From that rule, ref struct types can't declare methods that explicitly implement an interface method. Also, ref struct types must implement all methods declared in an interface, including those methods with a default implementation.

csharp
public interface ICoffee { } public ref struct Coffee : ICoffee { } Coffee coffee = new Coffee(); // This is not allowed ICoffee coffee2 = (ICoffee) coffee;

Hope you find this blog post useful. Happy coding!

You can download source code for this blog post for free

Download source code

Improve Your .NET and Architecture Skills

Join my community of 2400+ developers and architects.

Each week you will get 1 practical tip with best practises and architecture advice.