C# Source generator for enums
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:
- public static string GetName(this MyEnum value)
- public static string GetDescription(this MyEnum value)
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(); // falseReference 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 are in the Benchmark.net project Credfeto.Enumeration.Source.Generation.Benchmarks, with a summary of a run below.
| Method | Mean | Error | StdDev | Median | Allocated |
|---|---|---|---|---|---|
| GetNameToString | 25.5162 ns | 0.4146 ns | 0.3675 ns | 25.5322 ns | 24 B |
| GetNameReflection | 37.8875 ns | 0.3971 ns | 0.3520 ns | 37.8542 ns | 24 B |
| GetNameCachedReflection | 21.6571 ns | 0.4514 ns | 0.3770 ns | 21.6841 ns | 24 B |
| GetNameCodeGenerated | 0.0009 ns | 0.0039 ns | 0.0036 ns | 0.0000 ns | - |
| GetDescriptionReflection | 1,380.4979 ns | 15.1089 ns | 13.3937 ns | 1,382.9476 ns | 264 B |
| GetDescriptionCachedReflection | 22.8844 ns | 0.3856 ns | 0.3607 ns | 22.8364 ns | 24 B |
| GetDescriptionCodeGenerated | 0.0035 ns | 0.0057 ns | 0.0053 ns | 0.0000 ns | - |
| IsDefinedCodeReflection | 48.7961 ns | 0.9675 ns | 1.0352 ns | 48.5573 ns | 24 B |
| IsDefinedCodeReflectionCached | 21.4452 ns | 0.3169 ns | 0.2965 ns | 21.3938 ns | 24 B |
| IsDefinedCodeGenerated | 0.0012 ns | 0.0041 ns | 0.0037 ns | 0.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) 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>| Branch | Status |
|---|---|
| main | |
| release |
View changelog