DEV Community

Cover image for Why Can't User Types Have Literals in C#?
Akira Shimodate
Akira Shimodate

Posted on

Why Can't User Types Have Literals in C#?

Why Can't User Types Have Literals in C#?

C# allows us to write literals like this:

123L
1.5m
Enter fullscreen mode Exit fullscreen mode

These suffixes change the type of the literal.

  • Llong
  • mdecimal

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;
Enter fullscreen mode Exit fullscreen mode

These could mean:

  • 100_msTimeSpan
  • (1920,1080)_ptPoint
  • "abc.*"_regexRegex

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);
Enter fullscreen mode Exit fullscreen mode

If user-defined literals existed, we could instead write:

var t = 100_ms;
Enter fullscreen mode Exit fullscreen mode

The meaning would be identical.

But the code becomes closer to the domain.

Another Example

Point

Current code:

var p = new Point(1920,1080);
Enter fullscreen mode Exit fullscreen mode

Literal version:

var p = (1920,1080)_pt;
Enter fullscreen mode Exit fullscreen mode

Regex

Current code:

var r = new Regex("abc.*");
Enter fullscreen mode Exit fullscreen mode

Literal version:

var r = "abc.*"_regex;
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Then we could write:

var t = 100_ms;
Enter fullscreen mode Exit fullscreen mode

Another example:

public static Point operator _pt((int x, int y) coords)
    => new(coords.x, coords.y);

var p = (1920,1080)_pt;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

But semantically this is different.

Extension property interpretation:

100
↓
int
↓
extension property
↓
TimeSpan
Enter fullscreen mode Exit fullscreen mode

Literal interpretation:

100_ms
↓
TimeSpan
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

This allows conversions like:

literal → user type
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Physics / Simulation

var velocity = 30_mps;
var gravity = 9.8_mps2;
Enter fullscreen mode Exit fullscreen mode

Regex

var regex = @"^[a-z0-9_]+$"_regex;
Enter fullscreen mode Exit fullscreen mode

SQL DSL

var query = $"select * from Users where id={id}"_sql;
Enter fullscreen mode Exit fullscreen mode

UI Coordinates

var p = (1920,1080)_pt;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

User-defined literals would expand this to:

literal authority → any type
Enter fullscreen mode Exit fullscreen mode

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)