Skip to main content

CredFetoEnum by Mark Ridgwell

Nuget / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

Original Readme

note

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:

  • 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(); // 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

About

note

Enum / description to string

How to use

Example ( source csproj, source files )

This is the CSharp Project that references CredFetoEnum

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

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

<ItemGroup>
<PackageReference Include="Credfeto.Enumeration.Source.Generation" Version="1.1.0.138" OutputItemType="Analyzer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

using System;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;

namespace EnumClassDemo;

[GeneratedCode(tool: "Credfeto.Enumeration.Source.Generation.EnumGenerator", version: "1.1.0.138+a4e45a10ca3da5e916ae17843913bfff8c33cdef")]
public static class ColorsGeneratedExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetName(this Colors value)
{
return value switch
{
Colors.None => nameof(Colors.None),
Colors.Red => nameof(Colors.Red),
Colors.Green => nameof(Colors.Green),
Colors.Blue => nameof(Colors.Blue),
_ => ThrowInvalidEnumMemberException(value: value)
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetDescription(this Colors value)
{
return value switch
{
Colors.None => "This should be never seen",
_ => GetName(value)
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsDefined(this Colors value)
{
return value is Colors.None or Colors.Red or Colors.Green or Colors.Blue;
}

public static string ThrowInvalidEnumMemberException(this Colors value)
{
#if NET7_0_OR_GREATER
throw new UnreachableException(message: "Colors: Unknown enum member");
#else
throw new ArgumentOutOfRangeException(nameof(value), actualValue: value, message: "Unknown enum member");
#endif
}
}

Usefull

Download Example (.NET C# )

Share CredFetoEnum

https://ignatandrei.github.io/RSCG_Examples/v2/docs/CredFetoEnum

In the same category (Enum) - 4 other generators

EnumClass

EnumUtilities

FusionReactor

NetEscapades.EnumGenerators