Skip to content

Interop with C# Union Types and Closed Hierarchies #1464

@T-Gro

Description

@T-Gro

I propose we add interop support between F# discriminated unions and C#'s upcoming union types / closed hierarchies, enabling exhaustive pattern matching across the language boundary in both directions.

Full design discussion: [https://github.com//discussions/1463]

Why a separate discussion? C# unions is not one feature — it's a broad umbrella of 10 interlinked proposals (type unions, closed hierarchies, closed enums, case declarations, standard unions, target-typed access, inference features, type-value conversion). On the F# side, discriminated unions compile to 7 different IL layouts depending on case count, struct/ref, and attributes — each with different interop characteristics. The resulting matrix of "which C# feature × which F# layout" is too large for a single issue thread. The discussion has per-topic threads so each combination can be discussed independently.

The existing way of approaching this problem in F# is manually calling .Value on C# union types with no exhaustiveness, and C# consumers using .Tag switch + casts on F# DUs with no exhaustiveness.

Scope

This covers F#'s response to the C# union feature family:

C# Feature F# Action Discussion
Type unions (on Roslyn main) Recognize [Union], auto-unwrap Value, exhaustive match Topic A
Closed hierarchies Recognize [Closed], emit [Closed] on F# DUs Topic B
Closed enums Recognize + declare [<Closed>] enums Topic C
Case declarations Covered by closed hierarchies Topic D
Standard unions (Union<T1,T2>) Relationship to Choice<'T1,'T2> Topic E
Target-typed access open type + possible F# equivalent Topic F
Type value conversion Type-as-value resolution Topic G

Also related: target-typed inference, ctor inference, pattern inference — F# already handles these.

C# umbrella issue · proposals overview · Roslyn test plan (notes "Ping F# as FYI")

Pros and Cons

Advantages: Exhaustive pattern matching across F#/C# boundary. F# stays current with .NET. Natural extension of F#'s existing DU strength.

Disadvantages: Compiler complexity. C# spec still in preview (risk of churn).

Extra information

Estimated cost (XS, S, M, L, XL, XXL): L

Related suggestions:

  • #538 — Erased type-tagged anonymous union types
  • #1215 — Kotlin-like sealed classes
  • #1052 — Safe enums
  • #902 — Deconstruct on DUs for C#
  • #606 — Typed union cases

Affidavit (please submit!)

Please tick these items by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on StackOverflow) and I have searched StackOverflow for discussions of this issue
  • This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to the compiler and tooling repository
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions