RSCG – Aigamo.MatchGenerator
| name | Aigamo.MatchGenerator |
| nuget | https://www.nuget.org/packages/Aigamo.MatchGenerator/ |
| link | https://github.com/ycanardeau/MatchGenerator |
| author | Aigamo |
Generates exhaustive Match() extension methods for enums and abstract record hierarchies (tagged unions), ensuring compile-time safety — all cases must be handled.
How to use
1. Add [GenerateMatch] attribute to an enum or abstract record:
[GenerateMatch]
public enum CarTypes { None, Dacia, Tesla, BMW, Mercedes }
[GenerateMatch]
abstract record MaritalStatus;
sealed record Single : MaritalStatus;
sealed record Married : MaritalStatus;
2. Use the generated .Match() method — all cases required (compile error if any missing):
var msg = car.Match(
onBMW: () => “this is bmw”,
onDacia: () => “this is dacia”,
onMercedes: () => “this is mercedes”,
onNone: () => “this is none”,
onTesla: () => “this is tesla”
);
You can use for Transforming enums/records into exhaustive pattern matching (discriminated unions style).
If a case is missing in Match(), it’s a compile-time error
This is how you can use Aigamo.MatchGenerator .
The code that you start with is
<project sdk="Microsoft.NET.Sdk">
<propertygroup>
<outputtype>Exe</outputtype>
<targetframework>net10.0</targetframework>
<implicitusings>enable</implicitusings>
<nullable>enable</nullable>
</propertygroup>
<propertygroup>
<emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
<compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
</propertygroup>
<itemgroup>
<packagereference version="0.0.0-preview013" include="Aigamo.MatchGenerator">
</packagereference>
</itemgroup>
The code that you will use is
// See https://aka.ms/new-console-template for more information
using EnumDemo;
using System.Reflection;
Console.WriteLine("Hello, World!");
CarTypes car = CarTypes.BMW;
var message = car.Match(
onBMW: () => "this is bmw",
onDacia: () => "this is dacia",
onMercedes: () => "this is mercedes",
onNone: () => "this is none",
onTesla: () => "this is tesla"
);
Console.WriteLine(message);
MaritalStatus maritalStatus = new Divorced();
var messageStatus = maritalStatus.Match(
onSingle: x => "single",
onMarried: x => "married",
onDivorced: x => "divorced",
onWidowed: x => "widowed"
);
Console.WriteLine(messageStatus);
using Aigamo.MatchGenerator;
namespace EnumDemo;
[GenerateMatch]
public enum CarTypes
{
None,
Dacia,
Tesla,
BMW,
Mercedes,
}
[GenerateMatch]
abstract record MaritalStatus;
sealed record Single : MaritalStatus;
sealed record Married : MaritalStatus;
sealed record Divorced : MaritalStatus;
sealed record Widowed : MaritalStatus;
The code that is generated is
// <auto-generated>
using System;
using System.Diagnostics;
namespace EnumDemo;
public static class CarTypesMatchExtensions
{
public static U Match<u>(
this CarTypes value,
Func<u> onBMW,
Func<u> onDacia,
Func<u> onMercedes,
Func<u> onNone,
Func<u> onTesla
)
{
return value switch
{
CarTypes.BMW => onBMW(),
CarTypes.Dacia => onDacia(),
CarTypes.Mercedes => onMercedes(),
CarTypes.None => onNone(),
CarTypes.Tesla => onTesla(),
_ => throw new UnreachableException(),
};
}
}
using System; namespace Aigamo.MatchGenerator; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)] internal sealed class GenerateMatchAttribute : Attribute;
// <auto-generated>
using System;
using System.Diagnostics;
namespace EnumDemo;
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(),
};
}
}
// <auto-generated>
#nullable enable
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using TaggedEnum;
namespace EnumDemo;
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static class EnumDemoCarTypesExtension {
private static readonly Dictionary<global::enumdemo.cartypes , string=""> ValueNameMap = new(new EnumDemoCarTypesComparer()) {
{global::EnumDemo.CarTypes.None, "None"},
{global::EnumDemo.CarTypes.Dacia, "Dacia"},
{global::EnumDemo.CarTypes.Tesla, "Tesla"},
{global::EnumDemo.CarTypes.BMW, "BMW"},
{global::EnumDemo.CarTypes.Mercedes, "Mercedes"},
};
extension(global::EnumDemo.CarTypes self) {
public string Data {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
get =>
self switch {
global::EnumDemo.CarTypes.None => (string)"this is none",
global::EnumDemo.CarTypes.Dacia => (string)"this is dacia",
global::EnumDemo.CarTypes.Tesla => (string)"this is tesla",
global::EnumDemo.CarTypes.BMW => (string)"this is bwm",
global::EnumDemo.CarTypes.Mercedes => (string)"this is mercedes",
_ => DataNotFoundException.ThrowWithMessage<string>($"Data of {ValueNameMap[self]} not found.")
};
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static string ToStringFast(this global::EnumDemo.CarTypes self)
=> self switch {
global::EnumDemo.CarTypes.None => "None",
global::EnumDemo.CarTypes.Dacia => "Dacia",
global::EnumDemo.CarTypes.Tesla => "Tesla",
global::EnumDemo.CarTypes.BMW => "BMW",
global::EnumDemo.CarTypes.Mercedes => "Mercedes",
_ => UnreachableException.ThrowWithMessage<string>("Never reach here.")
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool HasName(this global::EnumDemo.CarTypes self, string name)
=> self.ToStringFast() == name;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool HasData(this global::EnumDemo.CarTypes self, string data)
=> self.Data == data;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool Equals(this global::EnumDemo.CarTypes self, global::EnumDemo.CarTypes v)
=> self == v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool TryGetDataByName(string name, [NotNullWhen(true)]out string? v) {
v = name switch {
"None" => (string)"this is none",
"Dacia" => (string)"this is dacia",
"Tesla" => (string)"this is tesla",
"BMW" => (string)"this is bwm",
"Mercedes" => (string)"this is mercedes",
_ => null
};
return v is not null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool TryGetValueByName(string name, [NotNullWhen(true)]out global::EnumDemo.CarTypes? v) {
v = name switch {
"None" => global::EnumDemo.CarTypes.None,
"Dacia" => global::EnumDemo.CarTypes.Dacia,
"Tesla" => global::EnumDemo.CarTypes.Tesla,
"BMW" => global::EnumDemo.CarTypes.BMW,
"Mercedes" => global::EnumDemo.CarTypes.Mercedes,
_ => null
};
return v is not null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public static bool TryGetValueByData(string data, [NotNullWhen(true)]out global::EnumDemo.CarTypes? v) {
v = data switch {
(string)"this is none" => global::EnumDemo.CarTypes.None,
(string)"this is dacia" => global::EnumDemo.CarTypes.Dacia,
(string)"this is tesla" => global::EnumDemo.CarTypes.Tesla,
(string)"this is bwm" => global::EnumDemo.CarTypes.BMW,
(string)"this is mercedes" => global::EnumDemo.CarTypes.Mercedes,
_ => null
};
return v is not null;
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
internal sealed class EnumDemoCarTypesComparer: IEqualityComparer<global::enumdemo.cartypes> {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(global::EnumDemo.CarTypes x, global::EnumDemo.CarTypes y) => x == y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetHashCode([DisallowNull] global::EnumDemo.CarTypes obj) => (int)obj;
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
internal sealed class EnumDemoCarTypesstringComparer: IEqualityComparer<string> {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(string? x, string? y) => x == y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetHashCode([DisallowNull] string obj) => obj.GetHashCode();
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesToDataConverter: JsonConverter<global::enumdemo.cartypes> {
public override global::EnumDemo.CarTypes Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string? token = reader.GetString();
return string.IsNullOrEmpty(token)
? JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't convert data \"{token}\" to global::EnumDemo.CarTypes.")
: EnumDemoCarTypesExtension.TryGetValueByData(token, out var result)
? result.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{token}\" in global::EnumDemo.CarTypes data.");
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes value, JsonSerializerOptions options) {
writer.WriteStringValue(value.Data);
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesArrayToDataArrayConverter: JsonConverter<global::enumdemo.cartypes []> {
public override global::EnumDemo.CarTypes[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByData(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes[] arr, JsonSerializerOptions options) {
writer.WriteStartArray();
for (int i = 0, len = arr.Length; i < len; ++i) {
writer.WriteStringValue(arr[i].Data);
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class NullableEnumDemoCarTypesArrayToDataArrayConverter: JsonConverter<global::enumdemo.cartypes ?[]> {
public override global::EnumDemo.CarTypes?[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes ?>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.Null:
list.Add(null);
continue;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByData(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes?[] arr, JsonSerializerOptions options) {
writer.WriteStartArray();
for (int i = 0, len = arr.Length; i < len; ++i) {
var v = arr[i];
if (v is null) {
writer.WriteNullValue();
} else {
writer.WriteStringValue(v.Value.Data);
}
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesEnumerableToDataEnumerableConverter: JsonConverter<ienumerable><global::enumdemo.cartypes>> {
public override IEnumerable<global::enumdemo.cartypes> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByData(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, IEnumerable<global::enumdemo.cartypes> values, JsonSerializerOptions options) {
writer.WriteStartArray();
foreach (var v in values) {
writer.WriteStringValue(v.Data);
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class NullableEnumDemoCarTypesEnumerableToDataEnumerableConverter: JsonConverter<ienumerable><global::enumdemo.cartypes ?>> {
public override IEnumerable<global::enumdemo.cartypes ?> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes ?>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.Null:
list.Add(null);
continue;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByData(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, IEnumerable<global::enumdemo.cartypes ?> values, JsonSerializerOptions options) {
writer.WriteStartArray();
foreach (var v in values) {
if (v is null) {
writer.WriteNullValue();
} else {
writer.WriteStringValue(v.Value.Data);
}
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesToNameConverter: JsonConverter<global::enumdemo.cartypes> {
public override global::EnumDemo.CarTypes Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string? token = reader.GetString();
return string.IsNullOrEmpty(token)
? JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't convert name \"{token}\" to global::EnumDemo.CarTypes.")
: EnumDemoCarTypesExtension.TryGetValueByName(token, out var result)
? result.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{token}\" in global::EnumDemo.CarTypes name.");
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes value, JsonSerializerOptions options) {
writer.WriteStringValue(value.ToStringFast());
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesArrayToNameArrayConverter: JsonConverter<global::enumdemo.cartypes []> {
public override global::EnumDemo.CarTypes[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByName(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes[] arr, JsonSerializerOptions options) {
writer.WriteStartArray();
for (int i = 0, len = arr.Length; i < len; ++i) {
writer.WriteStringValue(arr[i].ToStringFast());
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class NullableEnumDemoCarTypesArrayToNameArrayConverter: JsonConverter<global::enumdemo.cartypes ?[]> {
public override global::EnumDemo.CarTypes?[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes ?>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.Null:
list.Add(null);
continue;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByName(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes?[] arr, JsonSerializerOptions options) {
writer.WriteStartArray();
for (int i = 0, len = arr.Length; i < len; ++i) {
var v = arr[i];
if (v is null) {
writer.WriteNullValue();
} else {
writer.WriteStringValue(v.Value.ToStringFast());
}
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class EnumDemoCarTypesEnumerableToNameEnumerableConverter: JsonConverter<ienumerable><global::enumdemo.cartypes>> {
public override IEnumerable<global::enumdemo.cartypes> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByName(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, IEnumerable<global::enumdemo.cartypes> values, JsonSerializerOptions options) {
writer.WriteStartArray();
foreach (var v in values) {
writer.WriteStringValue(v.ToStringFast());
}
writer.WriteEndArray();
}
}
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")]
public sealed class NullableEnumDemoCarTypesEnumerableToNameEnumerableConverter: JsonConverter<ienumerable><global::enumdemo.cartypes ?>> {
public override IEnumerable<global::enumdemo.cartypes ?> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
var list = new List<global::enumdemo.cartypes ?>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonTokenType.StartArray:
continue;
case JsonTokenType.EndArray:
goto label;
case JsonTokenType.Null:
list.Add(null);
continue;
case JsonTokenType.String:
var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage<string>("JsonTokenType is string but reader.GetString() is null.") : token;
list.Add(EnumDemoCarTypesExtension.TryGetValueByName(
v,
out var item)
? item!.Value : JsonException.ThrowWithMessage<global::enumdemo.cartypes>($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name."));
continue;
default:
continue;
}
}
label:
return list.ToArray();
}
public override void Write(Utf8JsonWriter writer, IEnumerable<global::enumdemo.cartypes ?> values, JsonSerializerOptions options) {
writer.WriteStartArray();
foreach (var v in values) {
if (v is null) {
writer.WriteNullValue();
} else {
writer.WriteStringValue(v.Value.ToStringFast());
}
}
writer.WriteEndArray();
}
}
// <auto-generated>
#nullable enable
using System.Text.Json;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace TaggedEnum;
internal static class JsonExceptionExtensions {
extension(JsonException) {
[DoesNotReturn]
public static T ThrowWithMessage<t>(string msg)
=> throw new JsonException(msg);
}
}
internal static class UnreachableExceptionExtensions {
extension(UnreachableException) {
[DoesNotReturn]
public static T ThrowWithMessage<t>(string msg)
=> throw new UnreachableException(msg);
}
}
#pragma warning disable CA1050 // Declare types in namespaces
[AttributeUsage(
AttributeTargets.Field,
Inherited = false,
AllowMultiple = false
)]
internal sealed class Data<tvalue>(TValue v): Attribute {
public TValue V { get; private set; } = v;
}
[AttributeUsage(
AttributeTargets.Field,
Inherited = false,
AllowMultiple = false
)]
// TValue default is string
internal sealed class Data: Attribute {
public object? V { get; }
public Data(object str) {
V = str;
}
public Data() {}
}
#pragma warning restore CA1050 // Declare types in namespaces
#pragma warning disable CA1050 // Declare types in namespaces
[AttributeUsage(
AttributeTargets.Enum,
Inherited = false,
AllowMultiple = false
)]
internal sealed class Tagged<tvalue>: Attribute {
public bool Inline = true;
public bool UseSwitch = true;
public bool AllowDuplicate = false;
}
[AttributeUsage(
AttributeTargets.Enum,
Inherited = false,
AllowMultiple = false
)]
// TValue default is string
internal sealed class Tagged: Attribute {
public bool UseAll = false;
public bool Inline = true;
public bool UseSwitch = true;
public bool AllowDuplicate = false;
}
#pragma warning restore CA1050 // Declare types in namespaces
public sealed class DataNotFoundException(string msg): Exception(msg) {
[DoesNotReturn]
public static T ThrowWithMessage<t>(string message) => throw new DataNotFoundException(message);
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator