Was ist neu in .NET 9 & 10

Damian Kauth
Dezember 2025

C# 13: \e Escape Sequence

// .NET 9: Neue Escape-Sequenz für ANSI Codes
string escape = "\e";
string colored = $"\e[31mRot\e[0m";

Console.WriteLine($"\e[32mSuccess!\e[0m");
Console.WriteLine($"\e[91mError!\e[0m");

C# 13: Implicit Index Access

var numbers = new List<int> { 1, 2, 3, 4, 5 };

// NEU: Index-Operator für Listen!
var last = numbers[^1];
var secondLast = numbers[^2];
var lastThree = numbers[^3..];

Vorher nur für Arrays, jetzt auch für List<T>, Span<T>, etc.

C# 13: Lock Object

// Neuer dedizierter Lock Type
private readonly Lock _lock = new();

lock (_lock)
{
    // Bessere Performance
    // Deadlock-Detection
}

LINQ: CountBy & AggregateBy

var orders = GetOrders();

// .NET 9: CountBy
var orderCounts = orders.CountBy(o => o.CustomerId);

// AggregateBy
var totals = orders.AggregateBy(
    o => o.CustomerId,
    seed: 0m,
    (total, order) => total + order.Amount
);

30-50% schneller als GroupBy + Select

LINQ: Index()

var items = new[] { "A", "B", "C" };

// .NET 9: Index() Method
foreach (var (index, item) in items.Index())
{
    Console.WriteLine($"{index}: {item}");
}

var result = items
    .Index()
    .Where(x => x.Index > 0)
    .Select(x => x.Item);

HybridCache

// .NET 9: Neue Cache-Abstraktion
public class UserService(HybridCache cache)
{
    public async Task<User> GetUserAsync(int id)
    {
        return await cache.GetOrCreateAsync(
            $"user:{id}",
            async ct => await _db.GetUserAsync(id)
        );
    }
}

L1 (Memory) + L2 (Redis) automatisch, Tag-based invalidation

OpenAPI Built-in

// .NET 9: Kein Swashbuckle mehr nötig!
builder.Services.AddOpenApi();

var app = builder.Build();
app.MapOpenApi();

app.MapGet("/users/{id}", (int id) => { ... })
    .WithOpenApi();

C# 14: Extensions

// Extension Types - nicht nur Methods!
public extension StringExtensions for string
{
    public bool IsEmail => Contains('@') && Contains('.');
    
    public static string operator *(string s, int count) =>
        string.Concat(Enumerable.Repeat(s, count));
}

string email = "test@test.com";
bool valid = email.IsEmail;
string repeated = "abc" * 3; // "abcabcabc"

C# 14: Field Keyword

public class Person
{
    // Kein explizites Backing Field mehr nötig!
    public string Name { get; set => field = value?.Trim() ?? ""; }
    public string Email { get; init => field = value.ToLower(); }
}

EF Core 10: Complex Type Collections

// .NET 9: Complex Types nur singular
public class Order
{
    public Address ShippingAddress { get; set; }
}

// .NET 10: Collections von Complex Types!
public class Order
{
    public List<Address> Addresses { get; set; }
    public List<LineItem> Items { get; set; }
}

[ComplexType]
public class LineItem
{
    public string Product { get; set; }
    public int Quantity { get; set; }
}

// Wird in gleicher Tabelle gespeichert (JSON Column)

Fragen?

Vielen Dank!