Dev & Code Sep 3, 2026Add to bookmarks

Microsoft confirms via The Register the arrival of union types in C# in November 2026. A feature that TypeScript, Rust, Swift, and F# have had for a long time, and which changes the way business states are modeled in C#.
How many times have we written this kind of C# code to represent a state that can take three distinct forms?
public class PaymentResult
{
public bool IsSuccess { get; set; }
public string? TransactionId { get; set; }
public bool IsPending { get; set; }
public string? PendingReason { get; set; }
public bool IsError { get; set; }
public string? ErrorCode { get; set; }
public string? ErrorMessage { get; set; }
} An object where three booleans mutually exclude each other, five nullable fields that only make sense in combination with a specific boolean, and zero compiler guarantees that we won’t forget a case in the if/else. Welcome to modeling by convention, which relies on developer discipline—i.e., not much.
The Register announced on September 2, 2026, that Microsoft has confirmed the arrival of union types—also called "discriminated unions" or "sum types"—in C# in November 2026.
The idea is simple: instead of an object with five fields that "can be a success, pending, or an error," you explicitly declare to the compiler that the type is one of three mutually exclusive cases, each with its own relevant fields.
In pseudo-C# (the final syntax will be officially announced):
public union PaymentResult
{
Success(string TransactionId);
Pending(string Reason);
Error(string Code, string Message);
}
// Usage
switch (result)
{
case PaymentResult.Success s:
Console.WriteLine($"Transaction {s.TransactionId}");
break;
case PaymentResult.Pending p:
Console.WriteLine($"Pending: {p.Reason}");
break;
case PaymentResult.Error e:
Console.WriteLine($"Error {e.Code}: {e.Message}");
break;
// The compiler will flag if a case is missing
} The compiler checks the exhaustiveness of the switch: forgetting a case becomes an error, not a production bug discovered six months later.
F#, C#’s functional cousin in the same .NET ecosystem, has had discriminated unions forever—it’s one of the language’s historical selling points. Rust has made them a cornerstone of its design (the famous enum and match). Swift does too. TypeScript, in its own way, has had union types since 2015. Kotlin has sealed classes that approach the pattern. C# was lagging behind—you had to jury-rig abstract class hierarchies, sealed records, or third-party libraries like OneOf<T1,T2,T3>.
Three concrete consequences of this arrival:
OneOf and LanguageExt will reorganize. Part of what they offered becomes native; the rest (monads, partial application) remains useful.|> pipeline, default immutability), but the gap narrows—the question of language choice in a .NET project is now different.Union types in C# are F# seeping into C#—the editorial line of Mads Torgersen (C# lead designer) for several versions now. For our projects, the most immediate benefit is modeling API results (success/error/partial), workflow states (draft/in review/published), and polymorphic payloads (event sourcing, Kafka messages).
This isn’t revolutionary—the major languages have had it for 10 years. But for the .NET enterprise ecosystem, where C# remains the dominant language in business logic, it’s a qualitative leap in type safety. Worth testing as soon as the November preview lands.
Article produced by artificial intelligence, reviewed under human editorial control.