Skip to main content

Genbox.FastEnum by Ian Qvist

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: Genbox.FastEnum

Easy to use source generator for enums.

Author: Ian Qvist

NuGet: https://www.nuget.org/packages/Genbox.FastEnum/

You can find more details at https://github.com/Genbox/FastEnum

Source: https://github.com/Genbox/FastEnum

Author

note

Ian Qvist Alt text

Original Readme

note

FastEnum

NuGet License

Description

A source generator to generate common methods for your enum types at compile-time. Print values, parse, or get the underlying value of enums without using reflection.

Features

  • Intuitive API with discoverability through IntelliSense. All enums can be accessed via the Enums class.
  • High-performance
    • Zero allocations whenever possible.
    • GetMemberNames(), GetMemberValues() etc. are cached by default. Use DisableCache to disable it.
    • MemberCount and IsFlagsEnum is const to allow the compiler to fold constants.
  • Supports name and description from DisplayAttribute.
  • Support for flag enums via the FlagsAttribute.
  • Support for skipping enum values completely with [EnumOmitValue] on enum members.
  • Support for private/internal enums
  • Support for enums nested inside classes
  • Support for user-set underlying values such as long, uint, byte, etc.
  • Support for duplicate enum names from different namespaces
  • Support for enums that reside in the global namespace
  • Has several options to control namespace, class name and more for generated code. See Options section below for details.

Examples

Lets create a very simple enum, and add the [FastEnum] attribute to it.

[FastEnum]
public enum Color
{
Red,
Green,
Blue
}

Extensions

Extensions tell you something about an instance of an enum you have. For example, MyEnum.Value1.GetString() is the same as MyEnum.Value1.ToString() from dotnet, except that it does not need to do any work at runtime.

The following extensions are auto-generated:

Color c = Color.Red;

Console.WriteLine("String value: " + e.GetString());
Console.WriteLine("Underlying value: " + e.GetUnderlyingValue());

Output:

String value: Red
Underlying value: 0

Enums class

Enums is a class that contains metadata about the auto-generated enum.

Console.WriteLine("Number of members: " + Enums.Color.MemberCount);
Console.WriteLine("Parse: " + Enums.Color.Parse("Red"));
Console.WriteLine("Is Green part of the enum: " + Enums.Color.IsDefined(Color.Green));

PrintArray("Member names:", Enums.Color.GetMemberNames());
PrintArray("Underlying values:", Enums.Color.GetUnderlyingValues());

PrintArray simply iterates an array and list the values on separate lines.

Output:

Number of members: 3
Parse: Red
Is Green part of the enum: True
Member names:
- Red
- Green
- Blue
Underlying values:
- 0
- 1
- 2

Values via attributes

DisplayAttribute

If you add DisplayAttribute to an enum, the source generator will generate extra methods. For example, you can add [DisplayAttribute] to an enum value like this:

[FastEnum]
internal enum MyEnum
{
[Display(Name = "Value1Name", Description = "Value1Description")]
Value1 = 1,
Value2 = 2
}

It will generate GetDisplayName() and GetDescription() extensions to your enum.

MyEnum e = MyEnum.Value1;
Console.WriteLine("Display name: " + e.GetDisplayName());
Console.WriteLine("Description: " + e.GetDescription());

Output:

Display name: Value1Name
Description: Value1Description

FlagsAttribute

If you have an enum with the FlagsAttribute, FastEnum will add a method called IsFlagSet().

[Flags]
[FastEnum]
internal enum MyFlagsEnum
{
None = 0,
Value1 = 1,
Value2 = 2
Value3 = 4
}
MyFlagsEnum e = MyFlagsEnum.Value1 | MyFlagsEnum.Value3;
Console.WriteLine("Is Value2 set: " + e.IsFlagSet(MyFlagsEnum.Value2));

Output:

Is Value2 set: False

Options

[FastEnum] have several options to control the behavior of the generated code.

ExtensionClassName

The generated extension class is partial by default. So if you want to combine extension from your own class and the autogenerated one, you can use this option to set the name to the same as your extensions class. Defaults to <EnumName>Extensions.

ExtensionClassNamespace

Use this to control which namespace the extensions class belongs to. Defaults to the namespace of the enum.

EnumsClassName

Use this to set the name of the Enums class to something else.

EnumsClassNamespace

Used this to specify the namespace for the Enums class. Defaults to the namespace of the enum.

EnumNameOverride

Sometimes you might have two enums named the same, but in different namespaces. You can use this option to override the name of the enum in the generated code. For example, if your enum is named MyEnum the Enums class can be accessed like this:

Enums.MyEnum.GetMemberNames()

If you set EnumNameOverride to OtherEnum it will look like this instead:

Enums.OtherEnum.GetMemberNames()

DisableEnumsWrapper

Enable this to avoid generating the static Enums class that wraps all the enums. When enabled, Enums.MyEnum becomes MyEnum. This is handy if you want to set all enums inside the same namespace across projects. Note that you must use EnumNameOverride or set EnumsClassNamespace to something to avoid the name collision between your enum and the generated class.

DisableCache

By default arrays from GetMemberNames(), GetMemberValues() etc. is cached to avoid an allocation each time you call them. If your application only needs the arrays once, then caching them in memory take up unnecessary space. Use this option to disable the cache.

Transformations

You can transform the string output of enums with [EnumTransform] at compile time. There are a few ways to do this.

[EnumTransform(Preset = EnumTransform.UpperCase)] //Will uppercase all enum values
[EnumTransform(Regex = "/^Enum//")] //A regex to replace values starting with "Enum" with nothing.
[EnumTransform(CasePattern = "U_U_U")] //Uppercase the first, third and fifth characters

Note: You can only specify one [EnumTransform] at the time.

Regex must have the format /regex-here/replacement-here/.

CasePattern is a way to either uppercase, lowercase or omit charaters.

The language uses the following modifier chars:

  • U: Uppercase the char
  • L: Lowercase the char
  • O: Omit the char
  • _: Do nothing. Keep the char as-is.

Let's say you want to omit the first character in all values, uppercase the third character and lowercase the rest.

[FastEnum]
[EnumTransform(CasePattern = "OOULLLLL")]
public enum MyEnum
{
Myvalue1,
Myvalue2,
Myvalue3
}

The pattern is matched as much as possible. A pattern of U will simply uppercase the first character, and a pattern of UUUUUUUUUUUU will uppercase the first 12 characters, even if the enum value is only 6 characters long.

Omitting values

It is possible to omit enum value both fully and partially. This is useful if you, let's say, want to use the enum values directly in a dropdown on a website, but don't want to include a value in the list.

[FastEnum]
public enum Color
{
[EnumOmitValue] //Completely omitted
Unknown,

[EnumOmitValue(Exclude = EnumOmitExclude.GetMemberNames] //Partially omitted
Red,
Green
}

If you call GetMemberNames() or any other method on the Enums.Color class, the Unknown value will be omitted.

foreach (string name in Enums.Color.GetMemberNames())
{
Console.WriteLine(name);
}

Output:

Red
Green

Since we excluded GetMemberNames() for the Red color, it showed up in the list above, but it won't show up when calling GetMemberValues().

foreach (Color value in Enums.Color.GetMemberValues())
{
Console.WriteLine(value.ToString());
}

Output:

Green

Notes

Parse/TryParse methods

FastEnum has some additional features compared to dotnet's Enum.Parse<T>() and Enum.TryParse<T>():

  • Supports StringComparison (defaults to ordinal comparison)
  • Supports parsing ValueOverride when using [EnumTransformValue]. Also supports DisplayName and Description when using DisplayAttribute
  • You can enable/disable Name, Value, DisplayName or Description parsing via an enum: Enums.MyEnum.TryParse("val", out MyEnum v, MyEnumFormat.Name | MyEnumFormat.DisplayName)

IsDefined method

The IsDefined method is different than the one provided by dotnet. It supports flags out of the box. Enums.MyEnum.IsDefined((MyEnum)42) and Enums.MyEnum.IsDefined(MyEnum.Value1 | MyEnum.Value3) both work.

Benchmarks

Here are benchmarks for calling different methods in dotnet vs. using CodeGen vs. using Enums.net. Enums.net is a high-performance library for working with enum values.

The table below shows that Enums.net is between 2-80x faster than dotnet, but FastEnum is 2-14x faster than Enums.net.

MethodMeanErrorStdDevMedian
EnumHasFlag0.0056 ns0.0083 ns0.0074 ns0.0030 ns
CodeGenHasFlag0.0101 ns0.0062 ns0.0058 ns0.0083 ns
EnumsNetHasFlag0.6253 ns0.0238 ns0.0211 ns0.6192 ns
EnumIsDefined42.6278 ns0.4633 ns0.4334 ns42.5181 ns
CodeGenIsDefined0.0045 ns0.0066 ns0.0058 ns0.0013 ns
EnumsNetIsDefined0.4842 ns0.0101 ns0.0085 ns0.4845 ns
EnumLength20.5705 ns0.3509 ns0.5566 ns20.5117 ns
CodeGenLength0.0001 ns0.0004 ns0.0003 ns0.0000 ns
EnumsNetLength5.3362 ns0.1085 ns0.0906 ns5.3495 ns
EnumGetNames17.5890 ns0.2905 ns0.2717 ns17.6505 ns
CodeGenGetNames1.5764 ns0.0476 ns0.0446 ns1.5843 ns
EnumsNetGetNames1.6052 ns0.0323 ns0.0286 ns1.5994 ns
EnumToString15.3389 ns0.1815 ns0.1698 ns15.3113 ns
CodeGenToString0.8379 ns0.0380 ns0.0337 ns0.8267 ns
EnumsNetToString21.3269 ns0.0836 ns0.0653 ns21.3056 ns
ReflectionGetDisplayName1,008.3327 ns6.6111 ns5.8606 ns1,007.1464 ns
CodeGenGetDisplayName3.2780 ns0.1182 ns0.1495 ns3.2501 ns
EnumsNetGetDisplayName9.3953 ns0.1237 ns0.0966 ns9.4036 ns
EnumTryParse31.4662 ns0.4013 ns0.3557 ns31.3008 ns
CodeGenTryParse6.4197 ns0.0495 ns0.0463 ns6.4246 ns
EnumsNetTryParse41.8299 ns0.4277 ns0.4001 ns41.7159 ns
ReflectionTryParseDisplayName1,763.8422 ns17.7619 ns15.7455 ns1,764.9430 ns
CodeGenTryParseDisplayName3.9371 ns0.0177 ns0.0138 ns3.9381 ns
EnumsNetTryParseDisplayName40.4373 ns0.7966 ns0.7061 ns40.6816 ns
EnumGetValues0.0000 ns0.0000 ns0.0000 ns0.0000 ns
CodeGenGetValues2.2281 ns0.0281 ns0.0263 ns2.2237 ns
EnumsNetGetValues4.6160 ns0.0868 ns0.0769 ns4.6156 ns
EnumGetValues254.3910 ns2.2232 ns1.8565 ns253.8503 ns
CodeGenGetValues1.6647 ns0.0508 ns0.0475 ns1.6750 ns
EnumsNetGetValues2.4889 ns0.0416 ns0.0389 ns2.4874 ns

About

note

Generating values for enums

How to use

Example (source csproj, source files)

This is the CSharp Project that references Genbox.FastEnum

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Genbox.FastEnum" Version="1.0.0">
</PackageReference>
</ItemGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated />
// Generated by Genbox.FastEnum 1.0.0.0
// Generated on: 2025-08-29 11:58:11 UTC
#nullable enable
using System;

namespace EnumDemo;

[Flags]
public enum CarTypesFormat : byte
{
None = 0,
Name = 1,
Value = 2,
Default = Name | Value
}

Useful

Download Example (.NET C#)

Share Genbox.FastEnum

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Genbox.FastEnum

aaa

Category "Enum" has the following generators:

1 CredFetoEnum

2 EnumClass

3 EnumsEnhanced

4 EnumUtilities

5 Flaggen

6 FusionReactor

7 Genbox.FastEnum

8 jos.enumeration

9 NetEscapades.EnumGenerators

10 PMart.Enumeration

11 requiredenum

See category

Enum