EnumClass.Generator 1.3.0

dotnet add package EnumClass.Generator --version 1.3.0                
NuGet\Install-Package EnumClass.Generator -Version 1.3.0                
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="EnumClass.Generator" Version="1.3.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EnumClass.Generator --version 1.3.0                
#r "nuget: EnumClass.Generator, 1.3.0"                
#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.
// Install EnumClass.Generator as a Cake Addin
#addin nuget:?package=EnumClass.Generator&version=1.3.0

// Install EnumClass.Generator as a Cake Tool
#tool nuget:?package=EnumClass.Generator&version=1.3.0                

logo

enum class Generator

Summary

Type-safe source-generated alternative to C# enum inspired by Kotlin enum class

What is it?

This library contains source generator that creates class for specified enum. These classes contain similar functionality as original enum, but behave as ordinal class

Getting started

Installation

  1. Add reference to Nuget package
  • .NET CLI
dotnet add package EnumClass --version 1.2.0
  • Package Manager
Install-Package EnumClass -Version 1.2.0
  • PackageReference
<PackageReference Include="EnumClass" Version="1.2.0" />
  1. Specify Analyzer property in .csproj
<PackageReference Include="EnumClass" Version="1.2.0" OutputItemType="Analyzer"/>

Usage

Example usage

Add [EnumClass] attribute to enum

That is all! Corresponding class will be generated in namespace as your enum, but prefixed with EnumClass

Example

using EnumClass.Attributes;

namespace Domain
{
    [EnumClass]
    public enum PetKind
    {
        Cat,
        Dog
    }
    
    namespace EnumClass
    {
        public partial abstract class PetKind
        {
            public partial class CatEnumValue
            {
                public void SayMeow()
                {
                    System.Console.WriteLine("Meow!");
                }
            }
        }
    }
}

ToString()

All ToString() are generated at compile time. By default, they equal to name of corresponding member.

Console.WriteLine(EnumClass.PetKind.Cat.ToString() == "Cat"); 
// Output: true

If you want to override default value - use [EnumMemberInfo(StringValue = "")] attribute

namespace Domain;

[EnumClass]
public enum PetKind
{
    [EnumMemberInfo(StringValue = "Kitten")]
    Cat,
    Dog
}
// -------------

Console.WriteLine(EnumClass.PetKind.Cat.ToString());
// Output: Kitten

Cast to enum

All classes have overriden cast operator to original enum value

Console.WriteLine(((PetKind)EnumClass.PetKind.Cat) == PetKind.Cat); 
// Output: true

Cast to int

All classes have overriden cast to int

Console.WriteLine(((int)EnumClass.PetKind.Cat) == ((int)PetKind.Cat)); 
// Output: true

Equals()

Generated classes implement IEquatable<> both for enum class and original enum. Thus, has methods Equals(EnumClass) and Equals(OrignalEnum)

Console.WriteLine(EnumClass.PetKind.Cat.Equals(EnumClass.PetKind.Cat)); // Calls Equals(EnumClass.PetKind)
Console.WriteLine(EnumClass.PetKind.Cat.Equals(EnumClass.PetKind.Dog)); // Calls Equals(EnumClass.PetKind)
Console.WriteLine(EnumClass.PetKind.Cat.Equals(PetKind.Cat)); // Calls Equals(PetKind)
Console.WriteLine(EnumClass.PetKind.Cat.Equals(PetKind.Dog)); // Calls Equals(PetKind)
// Output: true
//         false
//         true
//         false

P.S. and of course Equals(object?)

Switch function

Instead of writing switch every time, a fimily of switch function is generated. They accepts both Action and Func with enum class at first argument and optional additional arguments.

E.g.

  1. Func<int>
var cat = EnumClass.PetKind.Cat;
var value = cat.Switch(1,
        (cat, i) => i + 1,
        (dog, i) => i * 100);
Console.WriteLine(value); 
// Output: 2
  1. Action
var dog = EnumClass.PetKind.Dog;
dog.Switch(
    cat => cat.SayMeow(),
    dog => Console.WriteLine("Oh, it is puppy!")); 
// Output: Oh, it is puppy!

TryParse

There is static function bool EnumClass.TryParse(string value, out EnumClass enumClass) for parsing values from raw enums. This function accepts strings with and without enum name: PetKind.Cat and Cat will be parsed into Cat value.

if (EnumClass.PetKind.TryParse("Cat", out var cat)
{
    Console.WriteLine($"This is cat!! {cat}");
}
else
{
    Console.WriteLine("This is not cat");
}

More

For more examples checkout samples folder

Features

Incremental generator

It uses incremental generator instead of source generator. This implies better performance in comparison

Custom target namespace

By default generated class contained in the same namespace as original enum + ".EnumClass" suffix. You can manually set target namespace in Namespace property of [EnumClass] attribute.

using EnumClass.Attributes;

namespace Test;

[EnumClass(Namespace = "Domain")]
public enum SampleEnum
{
    First,
    Second
}
//------------------
using Domain;

Console.WriteLine(SampleEnum.First);

Generate enum class for enum from another assembly

If you do not have access to enum source code directly, you can generate enum class for enum in external assembly. For this use [ExternalEnumClass] attribute.

// External assembly
namespace Logic;

public enum Word
{
    Single,
    Double,
    Triple
}
// Our assembly
using EnumClass.Attributes;
using Logic;

[assembly: ExternalEnumClass(typeof(Word), Namespace = "Another")]
namespace Another;

public partial class Word
{
    public abstract int WordsCount { get; }
    
    public partial class SingleEnumValue
    {
        public override int WordsCount => 1;    
    }
    
    
    public partial class DoubleEnumValue
    {
        public override int WordsCount => 2;    
    }
    
    
    public partial class TripleEnumValue
    {
        public override int WordsCount => 3;    
    }
}

Known limitations

Same name of member and enum

In the current implementation, static enum class field names have the same names as members of the original enum.

E.g.

[EnumClass]
public enum TokenType
{
    TokenType
}

will generate approximately the following code

public class TokenType
{
    public static TokenTypeEnumValue TokenType = new();
}

Half-baked

The project at an early stage of life. I'm sure there are lots of hidden bugs, so be cautious using it in production. In production may be better for now to use SmartEnum

Contributing

If you have an idea on how to improve the project or have found a bug, create an issue on GitHub

Give a star

If you want to see the continuation of the project, give it a star!

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.3.0 190 6/9/2023
1.2.0 136 5/28/2023
1.1.0 147 5/26/2023