C# 16 is redesigning the `unsafe` keyword to function as a caller-facing contract rather than just a syntax marker for pointer access. The new model, previewing in .NET 11 and targeting production in .NET 12, requires inner `unsafe {}` blocks at every unsafe call site, propagates unsafety explicitly through the call graph, and introduces `/// <safety>` documentation blocks to formalize caller obligations. Key changes include: `unsafe` on a member signature now defines a propagation contract; pointer types in signatures no longer implicitly propagate unsafety; a new `safe` keyword is required for `extern`/`LibraryImport` declarations; and unsafe fields can now carry documented invariants. The model closely mirrors Rust's approach and is motivated partly by AI-assisted code generation scaling software production faster than human review. A `dotnet format` migration fixer will assist adoption. The feature is opt-in via a new project-level property, with `AllowUnsafeBlocks=false` remaining the default.

54m read timeFrom devblogs.microsoft.com
Post cover image
Table of contents
Safety Copy linkThe model in a nutshell Copy linkThe model in practice Copy linkPropagation and suppression Copy linkProject-level opt-in Copy linkSafety documentation Copy linkSafety guards Copy linkUnsafe fields Copy linkA migration walkthrough Copy linkBinary distribution Copy linkRemaining design space Copy linkAnalogies Copy linkAI enablement Copy linkClosing Copy link
87.1K Impressions1 Comment