What's New in C# 10? A Developer's Guide to the Key Features

Explore the major new features in C# 10, including global usings, file-scoped namespaces, and record structs. Learn how these changes can make your .NET code cleaner and more concise.

C# 10, released alongside .NET 6, introduced a host of new features aimed at simplifying syntax, reducing boilerplate, and making the language more expressive. While there are many small improvements, a few key features stand out as game-changers for everyday C# development.

Let's dive into the most important new features in C# 10.

1. Global Using Directives

This is arguably the most impactful feature for reducing code clutter. How many times have you had the same list of using statements at the top of every file in your project? With global usings, you can declare a using statement once, in a single file, and it will apply to your entire project.

The Old Way: Every file would have this at the top:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

The New Way: Create a new file, perhaps named GlobalUsings.cs, and add the global keyword:

// GlobalUsings.cs
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;

Now, you don't need to add these using statements to any other file in your project. This significantly cleans up your code files, allowing you to focus on the code that matters.

2. File-Scoped Namespaces

Another great feature for reducing indentation and boilerplate is file-scoped namespaces. Instead of wrapping your entire file's content in a namespace block, you can declare the namespace for the whole file in a single line.

The Old Way:

namespace MyAwesomeApp.Services
{
    public class MyService
    {
        // ... code indented inside the namespace
    }
}

The New Way:

namespace MyAwesomeApp.Services;

public class MyService
{
    // ... code is no longer indented
}

This simple change removes a level of indentation from your files, making them cleaner and easier to read.

3. Record Structs

C# 9 introduced record class, a fantastic feature for creating immutable reference types. C# 10 extends this concept to value types with record struct.

Just like record classes, record structs automatically get value-based equality, a clean ToString() implementation, and init-only properties. This makes them perfect for creating small, immutable data structures where you want value-type semantics (i.e., they are copied by value, not by reference).

public readonly record struct Point(int X, int Y);

// Usage
var p1 = new Point(10, 20);
var p2 = new Point(10, 20);

Console.WriteLine(p1 == p2); // Output: True (value-based equality)
Console.WriteLine(p1);       // Output: Point { X = 10, Y = 20 }

4. Constant Interpolated Strings

A small but very welcome improvement. You can now declare const strings that are built using string interpolation, as long as all the interpolated values are also constants.

const string ApiVersion = "v1";
const string BaseUrl = $"https://api.example.com/{ApiVersion}";

Before C# 10, this was not possible and you would have had to use string concatenation (+), which is less readable.

5. Extended Property Patterns

Pattern matching continues to get more powerful in C# 10. You can now access nested properties and fields within a property pattern. This can make your if checks and switch expressions much more concise.

The Old Way:

if (order != null && order.Customer != null && order.Customer.Address != null && order.Customer.Address.Country == "USA")
{
    // ...
}

The New Way:

if (order is { Customer.Address.Country: "USA" })
{
    // ...
}

This is much more readable and less prone to null reference exceptions.

How These Features Work Together: Minimal APIs

All of these simplification features come together beautifully in the new Minimal APIs feature in .NET 6. You can now create a fully functional web API in just a few lines of code, in a single file.

// Program.cs
global using MyAwesomeApp.Data;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello, Minimal API!");

app.MapGet("/users/{id}", (int id, UserDbContext db) => 
{
    return db.Users.FindAsync(id);
});

app.Run();

This demonstrates the power of combining global usings, top-level statements (from C# 9), and lambda improvements to create incredibly concise applications.

Conclusion

C# 10 is focused on developer productivity and code clarity. Features like global usings and file-scoped namespaces remove ceremony and boilerplate, while improvements to records and pattern matching make your data modeling and logic more expressive. By adopting these new features, you can write C# code that is cleaner, more modern, and easier to maintain.