Skip to content

Build Not yet confirmed elsewhere1 publisher 2 min read Published

C# 15 unions make a missed switch case a CS8509 warning at compile time

C# 15 union types make the compiler flag every switch that misses a case with warning CS8509, so the throw-on-unreachable arm can go. They ship with .NET 11, now at RC1 with a go-live license but not final.

The Engineer · Build desk

How we use AI Send a correction

Same new case: a runtime throw, or a build warning How a new case type plays out in the post's marker-interface and union switches. The story has no quantity to chart, only versions and a date.

Marker-interface switch: the compiler demands a _ arm and the developer writes a throw. Adding Discontinued compiles, then the author's run threw InvalidOperationException. Union Pet(Cat, Dog) switch: no _ arm, no warning. Adding Discontinued to a union: warning CS8509 at every missed switch.

Same new case: a runtime throw, or a build warning
WhoHowKindClaim
Switch over marker interfaceCompiler demands a _ arm, so the developer writes a throw for a case that 'can't happen'constraint3
Interface gets DiscontinuedA teammate's new Discontinued record compiles; the author's run threw an unhandled InvalidOperationExceptionexposure4
Union Pet(Cat, Dog) switchDog and Cat arms with no _ arm give no warning; the compiler knows they are the whole listcapability6
Union gets DiscontinuedBuild reports warning CS8509 at every switch that missed the new casecapability9

What happened

  • A union declaration names a closed set of case types, a value is exactly one of them, and any case type converts to the union implicitly.
  • With a marker interface the compiler forced a discard arm, and a newly added Discontinued record compiled cleanly and then threw at runtime.
  • Assigning a type outside the union is a compile error; the post shows a string assigned to a Pet failing with CS0029.
  • A union of int and Guid works, mixing two types that could never share a base class or interface.

Why it matters

  • decision Teams choose whether a missed union case fails the build. CS8509 is a warning, and the post says it becomes a failed build only when TreatWarningsAsErrors is on.
  • constraint Adopting now means building on a release candidate, and Microsoft's docs say parts of the union proposal are not implemented yet.
  • exposure Existing marker-interface hierarchies keep their throw arms and their runtime failures until someone rewrites them as unions. The new check covers only switches over a union type.
  • capability Case types need no shared base and need not be the team's own, so a closed set can now span types from other libraries.

The `_` arm exists because the compiler cannot know that only three types implement the marker interface. [3] So it demands a fallback, and the usual filler is a throw for a case that "can't happen". [3]

Add a fourth record, `Discontinued`, and everything still compiles. [4] The post's author ran it and got an unhandled `InvalidOperationException` with the message "unreachable, promise". [4]

A union moves the list into the declaration. [5] A switch over `Pet`, with a `Dog` arm and a `Cat` arm and no discard arm, draws no warning, because the compiler knows those two are the whole list. [6] Add `Discontinued` to a union and every switch without an arm for it reports CS8509, naming the uncovered pattern. [9]

What the post shows is narrow. Its examples are a three-case lookup, a two-case `Pet` and an int-or-Guid `UserId`, with output reported from the author's own run. [15] The result carries over to a codebase only where the switches have no discard arm. In the interface version the compiler required that arm [3], and the missed case compiled past it [4]. We'd expect the arm to silence CS8509 on a union switch too. The post does not test that.

The setup cost is small on the RC1 SDK. The author's check was `#error version`, which reported language version 15.0, and the snippets compiled with no `LangVersion` set. [12] The `UnionAttribute` and `IUnion` types the compiler relies on have been in the runtime since .NET 11 Preview 5. [13] RC1 itself shipped on September 8, 2026. [14]

What to watch

  • Which union features Microsoft's docs still list as unimplemented, and whether they land between RC1 and the final .NET 11 release.
  • Reports from codebases that convert marker-interface hierarchies, since the post tests only small example records.
  • Whether a discard arm on a union switch silences CS8509, which the post does not test.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence68
Adoption
Insufficient
Hype gap−5
Incentives
Insufficient
Confidence62
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    C# 15 adds union types, declared in the form: union LookupResult(Found, NotFound, Invalid);

    Reported Supported Source: dev.to postView cited source
  2. [2]

    Union types ship with .NET 11, which is at Release Candidate 1: go-live licensed, but not final yet.

    Reported Supported Source: dev.to postView cited source
  3. [3]

    With a marker interface, the compiler cannot know that only three types implement the interface, so it demands a _ arm, and the developer writes a throw for a case that 'can't happen'.

    Reported Supported Source: dev.to postView cited source

Get this ledger inside ChatGPT. Ask about any of our stories and the answer brings its figure, each claim’s verdict and the sources. Free, no account.

Add to ChatGPTAdd to Claude

Sources

1 independent publisher whose own reporting we read for this story.

  1. dev.to

    1 article · October 13, 2026

    Stop Writing _ => throw for Cases That Can't Happen. C# 15 Has Unions

Share your take

Let Clarity write the post for you.

Signed-in readers get a short post drafted on this story in the register they choose — narrative, analytical, or a direct position — editable to the last word before it goes anywhere. The share buttons at the top of this story work without an account.

Topics and entities

Follow any of these and your For You feed starts watching them — no settings page required.

Topics

Loading related stories