Skip to main content

LayeredCraft.OptimizedEnums by LayeredCraft

NuGet / site data​

Nuget GitHub last commit GitHub Repo stars

Details​

Info​

info

Name: LayeredCraft.OptimizedEnums

High-performance alternative to SmartEnum using source generation. Provides zero-reflection, AOT-safe enum types with compile-time validation and O(1) lookup tables.

Author: LayeredCraft

NuGet: https://www.nuget.org/packages/LayeredCraft.OptimizedEnums/

You can find more details at https://github.com/layeredcraft/optimized-enums

Source: https://github.com/layeredcraft/optimized-enums

Author​

note

LayeredCraft Alt text

Original Readme​

note

LayeredCraft.OptimizedEnums​

LayeredCraft.OptimizedEnums is a modular C# .NET library providing high-performance, AOT-safe smart enum patterns using source generation. Inherit from a base class and the generator produces O(1) lookup tables, collection properties, and factory methods — all at compile time with zero reflection at runtime.

Key Features​
  • Zero reflection — all lookup tables are source-generated at compile time
  • AOT / trimming friendly — compatible with NativeAOT, ReadyToRun, and Blazor WASM
  • O(1) lookups — FromName, FromValue, ContainsName, ContainsValue
  • Compile-time validation — errors for missing partial, duplicate values/names
  • No allocations per call — all collections are statically cached
  • Inheritance-based triggering — no attribute required, just inherit and go
📦 Packages​
PackageNuGetDownloads
LayeredCraft.OptimizedEnumsNuGetDownloads
LayeredCraft.OptimizedEnums.SystemTextJsonNuGetDownloads
LayeredCraft.OptimizedEnums.EFCoreNuGetDownloads
LayeredCraft.OptimizedEnums.Dappercoming soon
LayeredCraft.OptimizedEnums.AutoFixturecoming soon

Build Status

Usage​
public sealed partial class OrderStatus : OptimizedEnum<OrderStatus, int>
{
public static readonly OrderStatus Pending = new(1, nameof(Pending));
public static readonly OrderStatus Paid = new(2, nameof(Paid));
public static readonly OrderStatus Shipped = new(3, nameof(Shipped));

private OrderStatus(int value, string name) : base(value, name) \{ }
}

Or use the int-defaulting convenience base class:

public sealed partial class Priority : OptimizedEnum<Priority>
{
public static readonly Priority Low = new(1, nameof(Low));
public static readonly Priority Medium = new(2, nameof(Medium));
public static readonly Priority High = new(3, nameof(High));

private Priority(int value, string name) : base(value, name) \{ }
}

The source generator produces:

// Lookup
var status = OrderStatus.FromName("Paid"); // OrderStatus.Paid
var status = OrderStatus.FromValue(3); // OrderStatus.Shipped

// Try-style
OrderStatus.TryFromName("Paid", out var result);
OrderStatus.TryFromValue(3, out var result);

// Membership
OrderStatus.ContainsName("Paid"); // true
OrderStatus.ContainsValue(99); // false

// Enumeration
IReadOnlyList<OrderStatus> all = OrderStatus.All;
IReadOnlyList<string> names = OrderStatus.Names;
IReadOnlyList<int> values = OrderStatus.Values;
int count = OrderStatus.Count; // compile-time constant
Performance​

Benchmarks run on Apple M3 Max, .NET 9.0.8, BenchmarkDotNet v0.14.0.

MethodMeanAllocated
FromName5.48 ns0 B
TryFromName4.53 ns0 B
FromValue2.18 ns0 B
TryFromValue1.21 ns0 B
ContainsName4.54 ns0 B
ContainsValue1.18 ns0 B
GetAll0.76 ns0 B
GetCount~0 ns0 B

All lookups are O(1) via statically-cached dictionaries. Count is a compile-time constant.

JSON Serialization​

Add LayeredCraft.OptimizedEnums.SystemTextJson for source-generated, zero-reflection JsonConverter support. One package is all you need — it pulls in the core package automatically:

dotnet add package LayeredCraft.OptimizedEnums.SystemTextJson

Decorate your class with [OptimizedEnumJsonConverter] and the generator emits a concrete, AOT-safe converter and wires it up via [JsonConverter]:

using LayeredCraft.OptimizedEnums;
using LayeredCraft.OptimizedEnums.SystemTextJson;

[OptimizedEnumJsonConverter(OptimizedEnumJsonConverterType.ByName)]
public sealed partial class OrderStatus : OptimizedEnum<OrderStatus, int>
{
public static readonly OrderStatus Pending = new(1, nameof(Pending));
public static readonly OrderStatus Paid = new(2, nameof(Paid));
public static readonly OrderStatus Shipped = new(3, nameof(Shipped));

private OrderStatus(int value, string name) : base(value, name) \{ }
}
{ "status": "Pending" }

Two strategies are available: ByName (serializes as the member name string) and ByValue (serializes as the underlying value). See the JSON Serialization docs for full details.

Entity Framework Core​

Add LayeredCraft.OptimizedEnums.EFCore for source-generated, zero-reflection EF Core value converter support. One package is all you need — it pulls in the core package automatically:

dotnet add package LayeredCraft.OptimizedEnums.EFCore

Decorate your class with [OptimizedEnumEfCore] and the generator emits concrete ValueConverter classes and registration helpers:

using LayeredCraft.OptimizedEnums;
using LayeredCraft.OptimizedEnums.EFCore;

[OptimizedEnumEfCore(OptimizedEnumEfCoreStorage.ByValue)]
public sealed partial class OrderStatus : OptimizedEnum<OrderStatus, int>
{
public static readonly OrderStatus Pending = new(1, nameof(Pending));
public static readonly OrderStatus Paid = new(2, nameof(Paid));
public static readonly OrderStatus Shipped = new(3, nameof(Shipped));

private OrderStatus(int value, string name) : base(value, name) \{ }
}

Register conversions with the global convention hook in your DbContext:

protected override void ConfigureConventions(ModelConfigurationBuilder builder)
{
builder.ConfigureOptimizedEnums();
}

Two strategies are available: ByValue (stores the underlying value) and ByName (stores the member name string). See the Entity Framework Core docs for full details.

Installation​
dotnet add package LayeredCraft.OptimizedEnums

Supports .NET 8.0, .NET 9.0, .NET 10.0.

Documentation​

Full documentation is available at the LayeredCraft.OptimizedEnums docs site.

License​

MIT

About​

note

A new way to define enums - and efficiently manage them

How to use​

Example (source csproj, source files)​

This is the CSharp Project that references LayeredCraft.OptimizedEnums

<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 Include="LayeredCraft.OptimizedEnums" Version="1.4.4" />
</ItemGroup>

</Project>

Generated Files​

Those are taken from $(BaseIntermediateOutputPath)\GX

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

#nullable enable

namespace EnumDemo;

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
partial class CarTypes
{
private static readonly global::System.Collections.ObjectModel.ReadOnlyCollection<global::EnumDemo.CarTypes> s_all =
global::System.Array.AsReadOnly(new global::EnumDemo.CarTypes[]
{
None,
Dacia,
Tesla,
BMW,
Mercedes
});

private static readonly global::System.Collections.ObjectModel.ReadOnlyCollection<string> s_names =
global::System.Array.AsReadOnly(new string[]
{
None.Name,
Dacia.Name,
Tesla.Name,
BMW.Name,
Mercedes.Name
});

private static readonly global::System.Collections.ObjectModel.ReadOnlyCollection<int> s_values =
global::System.Array.AsReadOnly(new int[]
{
None.Value,
Dacia.Value,
Tesla.Value,
BMW.Value,
Mercedes.Value
});

private static readonly global::System.Collections.Generic.Dictionary<string, global::EnumDemo.CarTypes> s_byName =
new global::System.Collections.Generic.Dictionary<string, global::EnumDemo.CarTypes>(5, global::System.StringComparer.Ordinal)
{
[None.Name] = None,
[Dacia.Name] = Dacia,
[Tesla.Name] = Tesla,
[BMW.Name] = BMW,
[Mercedes.Name] = Mercedes
};

private static readonly global::System.Collections.Generic.Dictionary<int, global::EnumDemo.CarTypes> s_byValue =
new global::System.Collections.Generic.Dictionary<int, global::EnumDemo.CarTypes>(5)
{
[None.Value] = None,
[Dacia.Value] = Dacia,
[Tesla.Value] = Tesla,
[BMW.Value] = BMW,
[Mercedes.Value] = Mercedes
};

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static global::System.Collections.Generic.IReadOnlyList<global::EnumDemo.CarTypes> All => s_all;

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static global::System.Collections.Generic.IReadOnlyList<string> Names => s_names;

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static global::System.Collections.Generic.IReadOnlyList<int> Values => s_values;

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public const int Count = 5;

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static global::EnumDemo.CarTypes FromName(string name)
{
if (!s_byName.TryGetValue(name, out var result))
throw new global::System.Collections.Generic.KeyNotFoundException(
$"'{name}' is not a valid name for CarTypes");

return result;
}

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static bool TryFromName(string name, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::EnumDemo.CarTypes? result) =>
s_byName.TryGetValue(name, out result);

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static global::EnumDemo.CarTypes FromValue(int value)
{
if (!s_byValue.TryGetValue(value, out var result))
throw new global::System.Collections.Generic.KeyNotFoundException(
$"'{value}' is not a valid value for CarTypes");

return result;
}

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static bool TryFromValue(int value, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::EnumDemo.CarTypes? result) =>
s_byValue.TryGetValue(value, out result);

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static bool ContainsName(string name) => s_byName.ContainsKey(name);

[global::System.CodeDom.Compiler.GeneratedCode("LayeredCraft.OptimizedEnums.Generator", "1.4.4.0")]
public static bool ContainsValue(int value) => s_byValue.ContainsKey(value);
}

Useful​

Download Example (.NET C#)​

Share LayeredCraft.OptimizedEnums​

https://ignatandrei.github.io/RSCG_Examples/v2/docs/LayeredCraft.OptimizedEnums

Category "Enum" has the following generators:​

1 Aigamo.MatchGenerator Nuget GitHub Repo stars 2026-04-08

2 CredFetoEnum Nuget GitHub Repo stars 2023-10-12

3 EnumClass Nuget GitHub Repo stars 2023-08-08

4 EnumsEnhanced Nuget GitHub Repo stars 2025-08-05

5 EnumUtilities Nuget GitHub Repo stars 2024-04-05

6 Flaggen Nuget GitHub Repo stars 2025-07-23

7 FusionReactor Nuget GitHub Repo stars 2024-04-06

8 Genbox.FastEnum Nuget GitHub Repo stars 2025-08-03

9 jos.enumeration Nuget GitHub Repo stars 2025-07-20

10 LayeredCraft.OptimizedEnums Nuget GitHub Repo stars 2026-09-06

11 LinkDotNet.Enumeration Nuget GitHub Repo stars 2026-05-14

12 NetEscapades.EnumGenerators Nuget GitHub Repo stars 2023-04-16

13 PMart.Enumeration NugetNuget GitHub Repo stars 2025-03-25

14 Porticle.Enumly Nuget GitHub Repo stars 2026-07-02

15 RapidEnum Nuget GitHub Repo stars 2025-10-04

16 requiredenum Nuget GitHub Repo stars 2025-08-14

17 TaggedEnum Nuget GitHub Repo stars 2026-04-05

See category​

Enum