Home

Awesome

credfeto-enum-source-generation

C# Source generator for enums

Using

Add a reference to the Credfeto.Enumeration.Source.Generation package in each project you need the code generation to run.

<ItemGroup>
  <PackageReference 
            Include="Credfeto.Enumeration.Source.Generation" 
            Version="1.0.0.11" 
            PrivateAssets="All" ExcludeAssets="runtime" />
</ItemGroup>

For each enum in the project, generates a class with the following extension methods:

Given an the example enum defined below:

public enum ExampleEnumValues
{
    ZERO = 0,

    [Description("One \"1\"")]
    ONE = 1,

    SAME_AS_ONE = ONE,
}

To get the name and value of the enum values. In release mode this can be practically instant.

ExampleEnumValues value = ExampleEnumValues.ONE;
 string name = value.GetName(); // ONE
 string description = value.GetDescription(); // One "1"
 bool isDefined = value.IsDefine(); // true
 bool isNotDefined = ((ExampleEnumValues)42).IsDefine(); // false

Enums in other assemblies

Reference the following package in the project that contains the enum extensions class to generate.

<ItemGroup>
    <PackageReference
            Include="Credfeto.Enumeration.Source.Generation.Attributes"
            Version="0.0.2.3"
            PrivateAssets="All" ExcludeAssets="runtime" />
</ItemGroup>

Add an EnumText attribute to a partial static extension class for each enum you want to expose.

[EnumText(typeof(System.Net.HttpStatusCode))]
[EnumText(typeof(ThirdParty.ExampleEnum))]
public static partial class EnumExtensions
{
}

Will generate the same extension methods, but for the types nominated in the attributes.

Benchmarks

Benchmarks are in the Benchmark.net project Credfeto.Enumeration.Source.Generation.Benchmarks, with a summary of a run below.

MethodMeanErrorStdDevMedianAllocated
GetNameToString25.5162 ns0.4146 ns0.3675 ns25.5322 ns24 B
GetNameReflection37.8875 ns0.3971 ns0.3520 ns37.8542 ns24 B
GetNameCachedReflection21.6571 ns0.4514 ns0.3770 ns21.6841 ns24 B
GetNameCodeGenerated0.0009 ns0.0039 ns0.0036 ns0.0000 ns-
GetDescriptionReflection1,380.4979 ns15.1089 ns13.3937 ns1,382.9476 ns264 B
GetDescriptionCachedReflection22.8844 ns0.3856 ns0.3607 ns22.8364 ns24 B
GetDescriptionCodeGenerated0.0035 ns0.0057 ns0.0053 ns0.0000 ns-
IsDefinedCodeReflection48.7961 ns0.9675 ns1.0352 ns48.5573 ns24 B
IsDefinedCodeReflectionCached21.4452 ns0.3169 ns0.2965 ns21.3938 ns24 B
IsDefinedCodeGenerated0.0012 ns0.0041 ns0.0037 ns0.0000 ns-
// * Warnings *
ZeroMeasurement
  EnumBench.GetNameCodeGenerated: Default        -> The method duration is indistinguishable from the empty method duration
  EnumBench.GetDescriptionCodeGenerated: Default -> The method duration is indistinguishable from the empty method duration
  EnumBench.IsDefinedCodeGenerated: Default      -> The method duration is indistinguishable from the empty method duration

// * Legends *
  Mean      : Arithmetic mean of all measurements
  Error     : Half of 99.9% confidence interval
  StdDev    : Standard deviation of all measurements
  Median    : Value separating the higher half of all measurements (50th percentile)
  Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
  1 ns      : 1 Nanosecond (0.000000001 sec)

Viewing Compiler Generated files

Add the following to the csproj file:

  <PropertyGroup>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <!-- Don't include the output from a previous source generator execution into future runs; the */** trick here ensures that there's
    at least one subdirectory, which is our key that it's coming from a source generator as opposed to something that is coming from
    some other tool. -->
    <Compile Remove="$(CompilerGeneratedFilesOutputPath)/*/**/*.cs" />
  </ItemGroup>

Build Status

BranchStatus
mainBuild: Pre-Release
releaseBuild: Release

Changelog

View changelog

Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <!-- markdownlint-restore --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END -->