Convert OneOf Code to Native C# Unions
Paste your OneOf<T0, T1, ...> type declarations and .Match()/.Switch() call sites. Get back the equivalent native union declaration and switch expression code.
How OneOfToUnion works
- 1
Paste your OneOf code
Include the method signature with OneOf<T0, T1, ...> as the return type. Optionally include .Match() or .Switch() call sites from the same method.
- 2
Type parameters are extracted
The tool parses the generic type arguments from OneOf<...>, correctly handling nested generics like Success<User>.
- 3
Union declaration is generated
The generic type parameters become the case types in a union declaration. The union name is derived from the method name.
- 4
Call sites are converted
Each .Match() lambda becomes a switch expression arm with the corresponding type pattern. .Switch() calls are converted similarly.
- 5
Boxing warnings are flagged
If any case type is a known value type (int, DateTime, Guid, etc.), the tool warns that boxing will occur when mixing value and reference types in the same union.
What the output means
Union declaration
The equivalent native union type. This replaces the OneOf<...> return type. Declare it once at namespace or class scope, then use the union name as the return type of your method.
Switch expression
The equivalent of your .Match() or .Switch() call site, written as a standard C# switch expression with type-pattern arms. Each arm maps to one lambda from the original call.
Case type badges
Each case type is shown as a badge. Value types (int, DateTime, Guid, etc.) are highlighted in amber to flag potential boxing.
Boxing warning
Shown when your union mixes value types and reference types. Value type cases get boxed into the union's internal object? storage, which adds heap allocation and GC pressure in hot paths.
Supported input patterns
| Pattern | Example |
|---|---|
| Method signature with OneOf return type | public OneOf<Receipt, Error> PlaceOrder(int id) { ... } |
| .Match() call with lambdas | result.Match(r => Ok(r), e => BadRequest(e.Message)) |
| .Match() with assignment | var response = result.Match(r => Ok(r), e => BadRequest(e.Message)); |
| .Switch() call (void) | result.Switch(r => Log(r), e => Console.WriteLine(e.Message)); |
| Nested generics | OneOf<Success<User>, NotFound, ValidationError> |
When to use this tool
| Scenario | What to paste |
|---|---|
| Bulk migration of OneOf usages | Each OneOf method signature + its call sites, one at a time |
| Verifying a manual conversion | The original OneOf code to check your hand-written union matches |
| Writing a migration PR | All OneOf usages in the file for consistent, mechanically-generated conversions |
| Learning the new syntax | Click 'Load example' to see a complete before/after conversion |
Frequently Asked Questions
How do I convert OneOf to a native C# union?
Paste your OneOf<T0, T1, ...> method signature into this tool. It generates the equivalent union type declaration. If you also paste .Match() or .Switch() call sites, it converts those to switch expressions with the correct case type patterns.
The conversion is a starting point. Always review and compile the output before committing, since the tool uses pattern matching rather than a full C# parser.
Does OneOf still work with .NET 11?
Yes. The OneOf NuGet package continues to work on .NET 11. Native union types are a new language feature, not a replacement that removes OneOf compatibility. You can migrate incrementally, converting individual usages to native unions while keeping the rest on OneOf.
What is the syntax difference between OneOf.Match and a union switch expression?
OneOf's .Match() takes a lambda parameter for each generic type argument. The native union equivalent is a C# switch expression with pattern-matching arms:
// OneOf .Match()
result.Match(
success => Ok(success.Value),
error => BadRequest(error.Message)
);
// Native union switch expression
result switch
{
Success s => Ok(s.Value),
Error e => BadRequest(e.Message),
};The switch expression uses standard C# pattern matching syntax. Each arm specifies a type pattern, optionally binding a variable, followed by the expression to evaluate.
Does the tool handle generic case types like Success<T>?
Yes. The parser correctly handles nested generic type arguments in OneOf declarations. OneOf<Success<User>, NotFound, ValidationError> is parsed as three case types: Success<User>, NotFound, and ValidationError.
Is my code sent to any server?
No. All parsing and conversion runs entirely in your browser using JavaScript string pattern matching. No code is sent anywhere, no cookies are set, and the tool works offline once the page has loaded.