Proposal: Tags #9449
Replies: 1 comment 2 replies
-
What controls this? Does the tag itself dictate that it can have a payload, or can any tag have a payload?
I see what this is going for, but I have concerns about this inline declaration syntax, especially since they are not strongly typed. If any/every
I'm not sure it would be compatible with that construct, given that they are based on the actual type, which in this case would always be
IMO would be better to have
Is it necessary to use a separate mechanism here rather than relying on string interning? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Proposal: Tags
Summary
This proposal introduces tags as a new primitive concept in C#. Tags are symbolic, strongly typed, lightweight values that act as both a type and a value. Inspired primarily by Roc’s tag system and influenced by atoms in Erlang, symbols in Ruby/JavaScript, and discriminated unions in F#/Rust, this feature enhances domain modeling and interplays naturally with the existing nominal type unions proposal.
Tags offer an ergonomic and type-safe alternative for representing sentinel values, results, events, symbolic messages, or lightweight enums—with or without payloads.
Motivation
C# developers often need to express simple symbolic variants—especially as return values, messages, or status codes. Today, options include:
Tags fill the gap by offering:
Syntax (Strawman)
Creating a tag
This declares a value
x
of type $MyTag, which is a tag with no payload.Explicit typing
Tags are first-class types as well as values. They are nominal, not stringly typed.
With payload
Tuple payloads are allowed:
In unions
Tags integrate seamlessly into nominal type unions:
Return types can mix tags and named records:
Use Cases
Results and Options:
Status indicators / sentinel values:
Inline union-like domain models:
Events / messages:
Implementation
Tags would be implemented as a small struct with a tag ID and optional data:
Global Tag Table
To avoid having to carry around a string per instance for the tag name, tag IDs are registered globally per AppDomain. For example:
The registry ensures:
This mirrors Erlang atoms, JavaScript symbols, or interned strings in .NET.
Compiler & Pattern Matching
The compiler knows how to:
Exhaustiveness checking can be performed when tags are used inside unions.
Advantages
Summary
Tags give C# a small but powerful feature that unlocks expressive, safe modeling for symbolic data. They pair naturally with unions and pattern matching and align C# more closely with the expressive power found in modern functional-first languages—while remaining intuitive and idiomatic for C# developers.
They also mean that the standard library does not need standard Option/Result types, as unions can be ad-hoc and can therefore have cases that perfectly fit the domain in which they're being used. For example:
Beta Was this translation helpful? Give feedback.
All reactions