Why Can't User Types Have Literals in C#?
C# allows us to write literals like this:
123L
1.5m
These suffixes change the type of the literal.
-
L→long -
m→decimal
This syntax is extremely convenient and natural.
But it raises an interesting question:
Why is this feature limited to built-in types?
What if user-defined types could have literal suffixes too?
For example:
var t = 100_ms;
var p = (1920,1080)_pt;
var r = "abc.*"_regex;
These could mean:
-
100_ms→TimeSpan -
(1920,1080)_pt→Point -
"abc.*"_regex→Regex
In other words, user types could participate in literal syntax.
The Current Way
Today, we typically write something like this:
var t = TimeSpan.FromMilliseconds(100);
If user-defined literals existed, we could instead write:
var t = 100_ms;
The meaning would be identical.
But the code becomes closer to the domain.
Another Example
Point
Current code:
var p = new Point(1920,1080);
Literal version:
var p = (1920,1080)_pt;
Regex
Current code:
var r = new Regex("abc.*");
Literal version:
var r = "abc.*"_regex;
These examples show how domain types could become first-class literals.
How Could This Be Defined?
One possible syntax could look like this:
public static TimeSpan operator _ms(double v)
=> TimeSpan.FromMilliseconds(v);
Then we could write:
var t = 100_ms;
Another example:
public static Point operator _pt((int x, int y) coords)
=> new(coords.x, coords.y);
var p = (1920,1080)_pt;
This gives user types an entry point into literal syntax.
Why Extension Properties Aren't the Same
A common alternative might be something like:
100.ms
But semantically this is different.
Extension property interpretation:
100
↓
int
↓
extension property
↓
TimeSpan
Literal interpretation:
100_ms
↓
TimeSpan
The difference is subtle but important.
Extension properties operate on values.
User-defined literals change how the literal itself is interpreted.
Why Doesn't C# Already Have This?
Most programming languages treat literals as built-in type privileges.
For example in C#:
123
1.5
"abc"
These are tied directly to built-in types.
Allowing user-defined literals would affect multiple parts of the compiler:
- lexer
- parser
- type binding
- IDE tooling
Because literals sit at the core of language syntax, they are traditionally restricted.
But Some Languages Already Do This
C++ introduced User Defined Literals (UDL).
auto t = 100ms;
This allows conversions like:
literal → user type
And it works surprisingly well in practice.
Potential Use Cases
User-defined literals could improve expressiveness in several domains.
Units
var delay = 100_ms;
var distance = 1.5_km;
Physics / Simulation
var velocity = 30_mps;
var gravity = 9.8_mps2;
Regex
var regex = @"^[a-z0-9_]+$"_regex;
SQL DSL
var query = $"select * from Users where id={id}"_sql;
UI Coordinates
var p = (1920,1080)_pt;
In these cases the code becomes closer to the domain language.
A Type System Perspective
This idea isn't just syntactic sugar.
Today C# effectively has:
literal authority → built-in types
User-defined literals would expand this to:
literal authority → any type
In other words, it would give user types literal citizenship.
This touches on deeper questions about type system design.
Proposal
I wrote a more detailed proposal here:
https://github.com/dotnet/csharplang/discussions/9605
I'd be curious to hear what other C# developers think about this idea.
Would user-defined literals make C# more expressive,
or would they introduce unnecessary complexity?
Top comments (0)