Explore union types in C# 15
C# 15 introduces union types, a highly anticipated feature designed to simplify handling multiple return types with compiler-enforced exhaustive pattern matching. This new addition aims to integrate seamlessly with existing C# patterns while providing type-safe, flexible data structures. The Hacker News community actively debates its design choices, comparing it to discriminated unions in F# and Rust, and discussing the increasing complexity of the C# language itself.
The Lowdown
Microsoft's .NET blog announces the preview release of union types in C# 15, a significant language addition available starting with .NET 11 Preview 2. This feature addresses long-standing challenges in C# development, particularly when methods need to return one of several possible types.
- Core Problem Solved: Previously, developers relied on imperfect solutions like
object, marker interfaces, or abstract base classes, which lacked compile-time guarantees or struggled with unrelated types. Union types provide a robust solution by declaring a closed set of case types that don't need a common ancestor. - Syntax and Functionality: The
unionkeyword allows declaring a type that can hold exactly one of a fixed set of types (e.g.,public union Pet(Cat, Dog, Bird);). The compiler enforces exhaustive pattern matching inswitchexpressions, ensuring all possible cases are handled. - Integration: Unions are designed for a C#-native experience, composing existing types and integrating with current pattern matching. They provide implicit conversions from case types and access the underlying value via a
Valueproperty. - Customization: For advanced scenarios or existing libraries, custom union types can be implemented using the
[System.Runtime.CompilerServices.Union]attribute, allowing for optimized storage strategies, including non-boxing access for value types. - Roadmap: Union types are part of a broader vision for comprehensive exhaustiveness in C#, alongside proposed features like closed hierarchies and closed enums.
This addition marks a notable step for C# towards more expressive and type-safe programming, particularly in handling diverse data structures with compile-time guarantees, inviting developers to try it out and provide feedback during its preview phase.
The Gossip
Union Distinctions: Ad-hoc vs. Nominal
Commenters immediately compare C#'s new nominal union types to 'ad-hoc' unions found in languages like F# or TypeScript. While some express disappointment that C# unions aren't 'on-the-fly' definitions, others argue that a formally declared, nominal approach (like C# offers) is beneficial for clarity and preventing 'messy' codebases, especially in large projects with complex type interactions.
C#'s Growing Complexity Conundrum
A significant portion of the discussion revolves around the direction of C# language design. Many users feel that by incorporating features from other languages, particularly functional ones, C# is becoming overly complex, a 'big bag of stuff' lacking clear vision. They contrast it with languages like Java, which some perceive as having a more cohesive roadmap, while defenders highlight that new features often reduce boilerplate and improve accessibility for new users, streamlining common patterns.
F# Comparisons and Trajectories
The introduction of union types inevitably draws comparisons to F#, where discriminated unions are a core feature. Some commenters lament that F# hasn't received the same level of attention as C#, suggesting it could have been 'the way' for functional programming on .NET. Others wonder if the continuous migration of F# features into C# diminishes F#'s unique appeal or if C# is simply adapting to modern programming paradigms, making the need for F# less pronounced.