Extension Indexers in C# 15: Finally, this[] on Types You Don't Own
C# 15 rounds out extension members with indexers, letting you add this[] syntax to types you can't modify. Here's how the syntax works, how resolution is prioritised against real indexers, and where the preview feature still bites.
LINQ Finally Gets FullJoin and Tuple-Returning Overloads in .NET 11
.NET 11 adds Enumerable.FullJoin for full outer joins and tuple-returning overloads for Join, GroupJoin, LeftJoin, and RightJoin, eliminating the result selector boilerplate that has plagued LINQ joins since 2007.
Closed Class Hierarchies in C# 15: Exhaustive Matching Comes to Inheritance
C# 15 introduces the closed modifier for class hierarchies, restricting derivation to the declaring assembly and enabling exhaustive switch expressions without a default arm. Here is how it works, how it differs from unions and sealed classes, and where it fits in domain modelling.
C# Is Redesigning unsafe: What Safety Contracts Mean for Your Code
C# is overhauling the unsafe keyword from a syntax gate into a formal safety contract system with propagation, suppression boundaries, and documentation requirements. Here is what changes, how it compares to Rust, and what you need to do to prepare.
Escape Analysis in .NET 10: How the JIT Eliminates Heap Allocations Automatically
The .NET 10 JIT compiler can now prove that many objects never leave their parent method and allocate them on the stack instead of the heap, eliminating GC pressure without any code changes.
Node.js Native Addons in C#: Replacing C++ and node-gyp with .NET Native AOT
The C# Dev Kit team replaced their C++ Node.js addon with C# compiled via .NET Native AOT, eliminating Python and node-gyp from their build chain. Here's how N-API, UnmanagedCallersOnly, and LibraryImport make it work.
UnsafeAccessorAttribute: Zero-Overhead Private Member Access Without Reflection
UnsafeAccessorAttribute lets you access private fields, methods, and constructors at the same speed as direct calls — no reflection, no Reflection.Emit, and full Native AOT compatibility. Here's how to use it, when it makes sense, and where developers trip up.
Writing Node.js Native Addons in C# with .NET Native AOT
Microsoft's C# Dev Kit team replaced their C++ Node.js addons with C# and Native AOT, eliminating Python dependencies and simplifying their build pipeline. Here is how N-API, UnmanagedCallersOnly, and a custom DLL import resolver make it work.
#:include Lands in .NET 11: File-Based Apps Finally Go Multi-File
.NET 11 Preview 3 adds the #:include and #:exclude directives to file-based apps, letting you split scripts across multiple files without reaching for a .csproj. Here is how they work, what they don't do, and where the edges still need sanding.
System.Text.Json in .NET 11: PascalCase, Per-Member Naming, and Type-Level Ignore
Three new features in .NET 11 Preview 3 give you fine-grained control over JSON serialisation: a built-in PascalCase naming policy, a per-member naming attribute, and type-level ignore conditions.
File-Based Apps in .NET 10: Scripts, Prototypes, and the End of Boilerplate
The dotnet run app.cs feature in .NET 10 lets you run C# from a single file with NuGet references, shebang support, and native AOT publishing -- no project file required. Here is how it works, where it shines, and where the edges still bite.
Post-Quantum Cryptography in .NET 10: ML-KEM, ML-DSA, and SLH-DSA from System.Security.Cryptography
With .NET 10 shipping built-in support for three NIST-standardised post-quantum algorithms, here is how ML-KEM, ML-DSA, and SLH-DSA work in practice, what the APIs look like, and what you need to watch out for on different platforms.
Collection Expression Arguments in C# 15: Passing Capacity, Comparers, and More with the with() Syntax
C# 15 adds the with() element to collection expressions, letting you pass constructor arguments like capacity and comparers directly inside the bracket syntax. Here is how it works, what it compiles to, and where it falls short.
Runtime Async in .NET 11: The End of Compiler-Generated State Machines
How .NET 11's runtime async moves async/await handling from the compiler into the runtime itself, delivering cleaner stack traces, better debugging, and reduced allocations without changing a line of your code.
Union Types in C# 15: Exhaustive Pattern Matching Without the Workarounds
C# 15 introduces union types with the union keyword, bringing implicit conversions, exhaustive switch expressions, and compiler-enforced closed type sets to .NET. Here is what they look like, how they lower to structs, and where they replace the OneOf hacks.
TimeProvider: Finally, Testable Time in .NET
How System.TimeProvider in .NET 8 replaces years of IClock wrappers with a first-class abstraction for testable, deterministic time — and how FakeTimeProvider makes testing time-dependent code straightforward.
.NET 9: The Features Worth Knowing About
A curated overview of the most impactful new features in .NET 9 for application developers.
Attribute-Driven Source Generation Patterns
Explore patterns for using marker attributes to drive source generation, including attribute discovery, property extraction, and handling edge cases.
Testing Source Generators with Microsoft.CodeAnalysis.Testing
A practical guide to testing source generators and analysers using the official Microsoft.CodeAnalysis.Testing framework.
Debugging Source Generators: Techniques That Actually Work
Practical strategies for debugging source generators, from Debugger.Launch() to emitting generated files to disk.
Incremental Source Generators: A Practical Guide
A hands-on introduction to incremental source generators, the modern replacement for ISourceGenerator that offers dramatically better IDE performance.
Writing a Custom Roslyn Analyser from Scratch
Build a custom Roslyn analyser that flags methods exceeding a configurable line count, complete with project setup and testing.
Syntax Trees and the Semantic Model: Roslyn's Two Pillars
Understand how Roslyn represents code as syntax trees and enriches it with semantic meaning through the semantic model.
The Result Pattern for Error Handling in .NET
How to replace exceptions with the Result pattern in .NET for predictable, composable error handling in your domain and application layers.
Domain-Driven Design Value Objects in C#
How to implement value objects in C# to encode domain rules, eliminate primitive obsession, and make invalid states unrepresentable.