N.SourceGenerators.UnionTypes 0.8.0
N.SourceGenerators.UnionTypes
Discriminated union type source generator
Motivation
C# doesn't support discriminated unions yet. This source generator helps automate writing union types with set of helper methods.
Getting Started
Add package reference to N.SourceGenerators.UnionTypes
dotnet add package N.SourceGenerators.UnionTypes
Create a partial class that will be used as a union type
public partial class FooResult
{
}
Add types you want to use in a discriminated union
public record Success(int Value);
public record ValidationError(string Message);
public record NotFoundError;
public partial class FooResult
{
}
Add N.SourceGenerators.UnionTypes.UnionTypeAttribute to a union type.
using N.SourceGenerators.UnionTypes;
public record Success(int Value);
public record ValidationError(string Message);
public record NotFoundError;
[UnionType(typeof(Success))]
[UnionType(typeof(ValidationError))]
[UnionType(typeof(NotFoundError))]
public partial class FooResult
{
}
Examples
All examples can be found in examples project
Implicit conversion
public FooResult ImplicitReturn()
{
// you can return any union type variation without creating FooResult
return new NotFoundError();
}
Explicit conversion
public ValidationError ExplicitCast(FooResult result)
{
return (ValidationError)result;
}
Match and MatchAsync methods are used to convert union type to another type. These methods force you to handle all possible variations.
public IActionResult MatchMethod(FooResult result)
{
return result.Match<IActionResult>(
success => new OkResult(),
validationError => new BadRequestResult(),
notFoundError => new NotFoundResult()
);
}
public async Task<IActionResult> MatchAsyncMethod(FooResult result, CancellationToken cancellationToken)
{
return await result.MatchAsync<IActionResult>(
static async (success, ct) =>
{
await SomeWork(success, ct);
return new OkResult();
}, static async (validationError, ct) =>
{
await SomeWork(validationError, ct);
return new BadRequestResult();
}, static async (notFoundError, ct) =>
{
await SomeWork(notFoundError, ct);
return new NotFoundResult();
}, cancellationToken);
static Task SomeWork<T>(T value, CancellationToken ct)
{
return Task.Delay(100, ct);
}
}
Match and MatchAsync methods are used to execute some work based on inner type
public void SwitchMethod(FooResult result)
{
result.Switch(
success => SomeWork(success),
validationError => SomeWork(validationError),
notFoundError => SomeWork(notFoundError)
);
static void SomeWork<T>(T value)
{
throw new NotImplementedException();
}
}
public async Task SwitchAsyncMethod(FooResult result, CancellationToken cancellationToken)
{
await result.SwitchAsync(
static async (success, ct) =>
{
await SomeWork(success, ct);
}, static async (validationError, ct) =>
{
await SomeWork(validationError, ct);
}, static async (notFoundError, ct) =>
{
await SomeWork(notFoundError, ct);
}, cancellationToken);
static Task SomeWork<T>(T value, CancellationToken ct)
{
return Task.Delay(100, ct);
}
}
Showing the top 20 packages that depend on N.SourceGenerators.UnionTypes.
| Packages | Downloads |
|---|---|
|
Zomp.SyncMethodGenerator
Generates synchronized method from async method
|
4 |
|
Zomp.SyncMethodGenerator
Generates synchronized method from async method
|
3 |
.NET Standard 2.0
- No dependencies.
| Version | Downloads | Last updated |
|---|---|---|
| 0.28.2 | 2 | 04/07/2026 |
| 0.28.2-rc.65 | 3 | 04/07/2026 |
| 0.28.1 | 2 | 04/07/2026 |
| 0.28.1-rc.63 | 2 | 04/07/2026 |
| 0.28.0 | 2 | 04/07/2026 |
| 0.28.0-rc.61 | 3 | 04/07/2026 |
| 0.28.0-rc.60 | 2 | 04/07/2026 |
| 0.27.0 | 1 | 04/07/2026 |
| 0.27.0-rc.58 | 2 | 04/07/2026 |
| 0.27.0-rc.57 | 2 | 04/07/2026 |
| 0.26.0 | 3 | 04/07/2026 |
| 0.26.0-rc.55 | 1 | 04/07/2026 |
| 0.26.0-rc.53 | 2 | 04/07/2026 |
| 0.26.0-rc.52 | 1 | 04/07/2026 |
| 0.26.0-rc.51 | 2 | 04/07/2026 |
| 0.26.0-rc.50 | 2 | 04/07/2026 |
| 0.26.0-rc.48 | 2 | 04/07/2026 |
| 0.25.3 | 2 | 04/07/2026 |
| 0.25.3-rc.41 | 1 | 04/07/2026 |
| 0.25.1-rc.40 | 1 | 04/07/2026 |
| 0.25.0-rc.39 | 1 | 04/07/2026 |
| 0.24.0 | 2 | 04/07/2026 |
| 0.24.0-rc.37 | 2 | 04/07/2026 |
| 0.23.0 | 2 | 04/07/2026 |
| 0.23.0-rc.35 | 2 | 04/07/2026 |
| 0.22.0 | 1 | 04/07/2026 |
| 0.22.0-rc.33 | 2 | 04/07/2026 |
| 0.21.0 | 1 | 04/07/2026 |
| 0.21.0-rc.31 | 1 | 04/07/2026 |
| 0.21.0-rc.30 | 2 | 04/07/2026 |
| 0.20.0-rc.29 | 1 | 04/07/2026 |
| 0.20.0-rc.28 | 1 | 04/07/2026 |
| 0.19.0 | 3 | 04/07/2026 |
| 0.18.0 | 1 | 04/07/2026 |
| 0.17.0 | 1 | 04/07/2026 |
| 0.16.0 | 1 | 04/07/2026 |
| 0.15.0 | 2 | 04/07/2026 |
| 0.14.0 | 3 | 04/07/2026 |
| 0.13.0 | 2 | 04/07/2026 |
| 0.12.0 | 3 | 04/07/2026 |
| 0.11.0 | 2 | 04/07/2026 |
| 0.10.0 | 1 | 04/07/2026 |
| 0.9.0 | 2 | 04/07/2026 |
| 0.8.0 | 2 | 04/07/2026 |
| 0.7.0 | 2 | 04/07/2026 |
| 0.6.0 | 1 | 04/07/2026 |
| 0.5.1 | 1 | 04/07/2026 |
| 0.5.0 | 3 | 04/07/2026 |
| 0.4.0 | 2 | 04/07/2026 |
| 0.3.0 | 1 | 04/07/2026 |
| 0.2.0 | 1 | 04/07/2026 |
| 0.1.0 | 1 | 04/07/2026 |