Aigamo.MatchGenerator
0.0.0-preview013
Prefix Reserved
dotnet add package Aigamo.MatchGenerator --version 0.0.0-preview013
NuGet\Install-Package Aigamo.MatchGenerator -Version 0.0.0-preview013
<PackageReference Include="Aigamo.MatchGenerator" Version="0.0.0-preview013" />
<PackageVersion Include="Aigamo.MatchGenerator" Version="0.0.0-preview013" />
<PackageReference Include="Aigamo.MatchGenerator" />
paket add Aigamo.MatchGenerator --version 0.0.0-preview013
#r "nuget: Aigamo.MatchGenerator, 0.0.0-preview013"
#:package Aigamo.MatchGenerator@0.0.0-preview013
#addin nuget:?package=Aigamo.MatchGenerator&version=0.0.0-preview013&prerelease
#tool nuget:?package=Aigamo.MatchGenerator&version=0.0.0-preview013&prerelease
MatchGenerator
Bring exhaustive pattern matching to C# enums and unions with zero boilerplate.
MatchGenerator is a Roslyn source generator that creates Match extension methods for your enums and discriminated-union-like types, enabling concise, expressive, and compile-time safe branching.
Features
- Generate
Matchextension methods for enums and unions - Exhaustive by design (no missing cases)
- Attribute-driven (opt-in per type)
- Supports generics (
Match<U>) - Respects effective accessibility
- Zero runtime cost (pure source generation)
Getting Started
1. Install the package
dotnet add package Aigamo.MatchGenerator
2. Annotate your type
Enum example
using Aigamo.MatchGenerator;
[GenerateMatch]
public enum Gender
{
Male = 1,
Female,
}
Union example
using Aigamo.MatchGenerator;
[GenerateMatch]
abstract record MaritalStatus;
sealed record Single : MaritalStatus;
sealed record Married : MaritalStatus;
sealed record Divorced : MaritalStatus;
sealed record Widowed : MaritalStatus;
3. Use Match
Enum
var message = gender.Match(
onMale: () => "male",
onFemale: () => "female"
);
Union
var message = maritalStatus.Match(
onSingle: x => "single",
onMarried: x => "married",
onDivorced: x => "divorced",
onWidowed: x => "widowed"
);
Why use MatchGenerator?
Without MatchGenerator
Enum
var message = gender switch
{
Gender.Male => "male",
Gender.Female => "female",
_ => throw new UnreachableException(),
};
Union
var message = maritalStatus switch
{
Single x => "single",
Married x => "married",
Divorced x => "divorced",
Widowed x => "widowed",
_ => throw new UnreachableException(),
};
With MatchGenerator
var message = gender.Match(
onMale: () => "male",
onFemale: () => "female"
);
- More concise
- More readable
- No default case required
- Compile-time safety
Exhaustiveness Guarantee
All cases must be handled.
If a new enum value or union type is added:
public enum Gender
{
Male = 1,
Female,
Other,
}
or
sealed record Separated : MaritalStatus;
Existing Match calls will fail to compile until updated. This ensures no cases are missed.
Generated Code (Example)
Enum
internal static class GenderMatchExtensions
{
public static U Match<U>(
this Gender value,
Func<U> onFemale,
Func<U> onMale
)
{
return value switch
{
Gender.Female => onFemale(),
Gender.Male => onMale(),
_ => throw new UnreachableException(),
};
}
}
Union
internal static class MaritalStatusMatchExtensions
{
public static U Match<U>(
this MaritalStatus value,
Func<Divorced, U> onDivorced,
Func<Married, U> onMarried,
Func<Single, U> onSingle,
Func<Widowed, U> onWidowed
)
{
return value switch
{
Divorced x => onDivorced(x),
Married x => onMarried(x),
Single x => onSingle(x),
Widowed x => onWidowed(x),
_ => throw new UnreachableException(),
};
}
}
References
- Introducing C# Source Generators - .NET Blog
- roslyn/docs/features/source-generators.cookbook.md at main · dotnet/roslyn
- roslyn/docs/features/incremental-generators.cookbook.md at main · dotnet/roslyn
- Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F# by Scott Wlaschin
- It Seems the C# Team Is Finally Considering Supporting Discriminated Unions - DEV Community
- salvois/DiscriminatedOnions: A stinky but tasty hack to emulate F#-like discriminated unions in C#
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.0-preview013 | 34 | 4/3/2026 |
| 0.0.0-preview012 | 34 | 4/2/2026 |
| 0.0.0-preview011 | 41 | 4/1/2026 |
| 0.0.0-preview010 | 25 | 4/1/2026 |
| 0.0.0-preview009 | 30 | 4/1/2026 |
| 0.0.0-preview008 | 30 | 4/1/2026 |
| 0.0.0-preview007 | 37 | 3/31/2026 |
| 0.0.0-preview006 | 43 | 3/30/2026 |
| 0.0.0-preview005 | 43 | 3/29/2026 |
| 0.0.0-preview004 | 38 | 3/29/2026 |
| 0.0.0-preview003 | 38 | 3/29/2026 |
| 0.0.0-preview002 | 39 | 3/29/2026 |
| 0.0.0-preview001 | 38 | 3/29/2026 |