EnumToClass 1.0.8

dotnet add package EnumToClass --version 1.0.8
                    
NuGet\Install-Package EnumToClass -Version 1.0.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EnumToClass" Version="1.0.8">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EnumToClass" Version="1.0.8" />
                    
Directory.Packages.props
<PackageReference Include="EnumToClass">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EnumToClass --version 1.0.8
                    
#r "nuget: EnumToClass, 1.0.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EnumToClass@1.0.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EnumToClass&version=1.0.8
                    
Install as a Cake Addin
#tool nuget:?package=EnumToClass&version=1.0.8
                    
Install as a Cake Tool

EnumToClass Generator

C# source generator that turns an enum into a smart-enum style closed class/record: constant string names, flyweight instances, lookup helpers, and conversions.

The type decorated with EnumToClassAttribute<TEnum> becomes a closed type with a private constructor and readonly properties.

Attribute

/// <summary>
/// Generates const string values for each enum field.
/// Makes class/record decorated with the attribute a closed type.
/// </summary>
/// <typeparam name="T">Enum type parameter</typeparam>
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = false)]
[global::System.Diagnostics.Conditional("ENUM_TO_CLASS_GENERATOR_ATTRIBUTES")]
internal sealed class EnumToClassAttribute<T> : global::System.Attribute
    where T : global::System.Enum
{
    public bool WithDescription { get; set; }
}

Optional properties

  1. WithDescription — when true, generates a Description property. Value resolution order:
    1. DescriptionAttribute on the enum field, if present
    2. Full text of the XML documentation <summary> (all lines, newline-separated), if present
    3. The enum member name

Projecting enum-member attributes as properties

Opt-in companion attribute (can be applied multiple times):

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[Conditional("ENUM_TO_CLASS_GENERATOR_ATTRIBUTES")]
internal sealed class EnumToClassPropertyAttribute<TAttribute> : Attribute
    where TAttribute : Attribute
{
    /// <summary>Generated property name. Default: TAttribute name without "Attribute" suffix.</summary>
    public string? Name { get; set; }

    /// <summary>
    /// When true, property type is an array (all applications on the member; empty array if none).
    /// When false (default), first application or null.
    /// </summary>
    public bool AsArray { get; set; }

    /// <summary>
    /// When set, project this member of TAttribute (property or ctor parameter) instead of the attribute instance.
    /// Single segment only (e.g. "Name").
    /// </summary>
    public string? Source { get; set; }

    /// <summary>
    /// When true, emit a bool: whether TAttribute is applied on the enum member.
    /// Incompatible with AsArray and Source.
    /// </summary>
    public bool AsBoolean { get; set; }
}

Example:

[EnumToClass<TestEnum>]
[EnumToClassProperty<Metadata1Attribute>]
[EnumToClassProperty<Metadata2Attribute>(Name = "Meta2")]
[EnumToClassProperty<PermissionAttribute>(AsArray = true, Name = "Permissions", Source = "Name")]
[EnumToClassProperty<AdminOnlyAttribute>(AsBoolean = true, Name = "HasAdminOnly")]
public sealed partial class TestEnumClass { }

Generates properties filled from each enum member’s attributes via object initializers on the static map (constructor stays slim):

AsBoolean AsArray Source Host type Value
false false (null) TAttribute? instance / null
false true (null) TAttribute[] instances / empty
false false "Name" e.g. string? member value / null
false true "Name" e.g. string[] values / empty
true false (null) bool attribute present / absent

AsBoolean cannot be combined with AsArray or Source (ETC015). Nested Source paths are not supported. Only reconstructible attribute/member values are supported for non-boolean modes.

Equality still compares Value only — projected attribute properties do not participate in Equals / ==.

Diagnostics

Id Severity Meaning
ETC001 Error Host type is not partial
ETC002 Warning Enum has no named members
ETC003 Error Host type is nested (not supported; generation skipped)
ETC010 Warning Attribute type cannot be reconstructed as a property value
ETC011 Error Duplicate EnumToClassProperty<T> for the same T
ETC012 Error Invalid or conflicting projected property name
ETC014 Error Invalid Source member on EnumToClassProperty
ETC015 Error Conflicting EnumToClassProperty options (AsBoolean vs AsArray/Source)

Usage

namespace EnumToClass.Tests.Integration;

public enum TestElements
{
    None,
    Element1,
    Element2,
    Element3
}

[EnumToClass<TestElements>]
internal sealed partial class TestElementClass
{
}

[EnumToClass<TestElements>(WithDescription = true)]
public sealed partial record TestElementRecord
{
}

Semantics

  • IsEmpty: true when Value == default(TEnum).
  • Empty: shared instance for the default enum value. If a named member equals default(TEnum), Empty is the same reference as that member’s *Instance (and map entry). Missing names from GetByName return Empty.
  • Flyweight: named members are created once in a static map; conversions and *Instance properties return those instances.
  • GetByName: ordinal, case-sensitive name match; unknown name → Empty.
  • TryGetByName: returns false on miss (and sets value to Empty).
  • Classes implement IEquatable<T> and == / != by Value. Records use built-in record equality.
  • [Flags] / combined values: conversion from enum uses ToString(); combined flag names are not map keys, so lookup yields Empty. Flags-aware parsing is out of scope.
  • Nested host types: not supported — generator reports ETC003 and skips code generation (partials would be emitted at namespace scope).

Generated surface (illustrative)

For a partial class host the generator emits (among other members):

  • ValueByNameMap (private)
  • Empty, Name, Value, IsEmpty
  • public const string MemberName and public static T MemberNameInstance per enum member
  • GetAll(), GetByName, TryGetByName
  • Implicit conversions: string, TEnum, underlying integral type ↔ host type
  • When using [EnumToClassProperty<T>]: nullable properties for those attribute types

Change Log

Version 1.0.8

  1. Hardening: Empty flyweight, escaped literals, constant-only enum members, class IEquatable/==, TryGetByName, ETC001ETC003, global:: BCL types, doc indent, full <summary> for Description.
  2. EnumToClassPropertyAttribute<T>: project selected enum-member attributes as host properties (Name, AsArray, Source, AsBoolean). Diagnostics ETC010ETC012, ETC014ETC015.

Version 1.0.7

  1. Add implicit operator to convert underlying enum type value to Class type.

Version 1.0.6

  1. Add optional description property generation

Version 1.0.5

  1. Add documentation comments based on DescriptionAttribute value.
  2. Fix full enum type name for external enums.
  3. Fix documentation comments for external enums.

Version 1.0.4

  1. Add documentation comments to generated const values based on documentation comments for the enum element

Version 1.0.3

  1. Fix method names in generator.
  2. Replace reflection generated to generator generated values dictionary.
  3. Add GetAll() static function to the class with EnumToClassAttribute attribute.
  4. Add implicit operator to convert enum type value to underlying enum type.
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.8 95 8/11/2026
1.0.7 135 3/11/2026
1.0.6 250 10/3/2024
1.0.5 189 9/23/2024
1.0.4 195 9/23/2024
1.0.3 183 9/20/2024
1.0.2 222 9/14/2024