SmartEnum
A base class for quickly and easily creating strongly typed enum replacements in C#.
Install / Use
/learn @ardalis/SmartEnumREADME
Table Of Contents
- Table Of Contents
- SmartEnum
- Install
- Usage
- List
- FromName()
- FromValue()
- ToString()
- Switch
- SmartFlagEnum
- Setting SmartFlagEnum Values
- Usage - (SmartFlagEnum)
- FromName()
- FromValue()
- FromValueToString()
- BitWiseOrOperator
- Persisting with EF Core 2.1 or higher
- Using SmartEnum.EFCore
- AutoFixture support
- Json support
- Dapper support
- DapperSmartEnum
- Case Insensitive String Enum
- Name Validation Attribute
- Examples in the Real World
- References
Sub-packages
Give a Star! :star:
If you like or are using this project please give it a star. Thanks!
Smart Enum
An implementation of a type-safe object-oriented alternative to C# enum.
Contributors
Thanks to Scott DePouw, Antão Almada, and Nagasudhir Pulla for help with this project!
Install
The framework is provided as a set of NuGet packages. In many cases you'll only need the base package, but if you need serialization and/or ORM support there are many implementation-specific packages available to assist.
To install the minimum requirements:
Install-Package Ardalis.SmartEnum
To install support for serialization, AutoFixture, EF Core, Model Binding, or Dapper select the lines that apply:
Install-Package Ardalis.SmartEnum.AutoFixture
Install-Package Ardalis.SmartEnum.JsonNet
Install-Package Ardalis.SmartEnum.SystemTextJson
Install-Package Ardalis.SmartEnum.Utf8Json
Install-Package Ardalis.SmartEnum.MessagePack
Install-Package Ardalis.SmartEnum.ProtoBufNet
Install-Package Ardalis.SmartEnum.EFCore
Install-Package Ardalis.SmartEnum.ModelBinding
Install-Package Ardalis.SmartEnum.Dapper
Version
The latest version of the package supports .NET 8 and NetStandard 2.0.
Usage
Define your smart enum by inheriting from SmartEnum<TEnum> where TEnum is the type you're declaring. For example:
using Ardalis.SmartEnum;
public sealed class TestEnum : SmartEnum<TestEnum>
{
public static readonly TestEnum One = new TestEnum(nameof(One), 1);
public static readonly TestEnum Two = new TestEnum(nameof(Two), 2);
public static readonly TestEnum Three = new TestEnum(nameof(Three), 3);
private TestEnum(string name, int value) : base(name, value)
{
}
}
The default value type is int but it can be set using the second generic argument TValue.
The string alias can also be set explicitly, where spaces are allowed.
using Ardalis.SmartEnum;
public sealed class TestEnum : SmartEnum<TestEnum, ushort>
{
public static readonly TestEnum One = new TestEnum("A string!", 1);
public static readonly TestEnum Two = new TestEnum("Another string!", 2);
public static readonly TestEnum Three = new TestEnum("Yet another string!", 3);
private TestEnum(string name, ushort value) : base(name, value)
{
}
}
Just like regular enum, more than one string can be assigned to the same value but only one value can be assigned to a string:
using Ardalis.SmartEnum;
public sealed class TestEnum : SmartEnum<TestEnum>
{
public static readonly TestEnum One = new TestEnum(nameof(One), 1);
public static readonly TestEnum Two = new TestEnum(nameof(Two), 2);
public static readonly TestEnum Three = new TestEnum(nameof(Three), 3);
public static readonly TestEnum AnotherThree = new TestEnum(nameof(AnotherThree), 3);
// public static TestEnum Three = new TestEnum(nameof(Three), 4); -> throws exception
private TestEnum(string name, int value) : base(name, value)
{
}
}
In this case, TestEnum.FromValue(3) will return the first instance found, either TestEnum.Three or TestEnum.AnotherThree. No order should be assumed.
The Value content is used when comparing two smart enums, while Name is ignored:
TestEnum.One.Equals(TestEnum.One); // returns true
TestEnum.One.Equals(TestEnum.Three); // returns false
TestEnum.Three.Equals(TestEnum.AnotherThree); // returns true
Inheritance can be used to add "behavior" to a smart enum.
This example adds a BonusSize property, avoiding the use of the switch typically used with regular enums:
using Ardalis.SmartEnum;
public abstract class EmployeeType : SmartEnum<EmployeeType>
{
public static readonly EmployeeType Manager = new ManagerType();
public static readonly EmployeeType Assistant = new AssistantType();
private EmployeeType(string name, int value) : base(name, value)
{
}
public abstract decimal BonusSize { get; }
private sealed class ManagerType : EmployeeType
{
public ManagerType() : base("Manager", 1) {}
public override decimal BonusSize => 10_000m;
}
private sealed class AssistantType : EmployeeType
{
public AssistantType() : base("Assistant", 2) {}
public override decimal BonusSize => 1_000m;
}
}
You can take this a step further and use the ManagerType and associated BonusSize property in a parent class like so:
public class Manager
{
private ManagerType _managerType { get; set; }
public string Type
{
get => _managerType.Name;
set
{
if (!Manag
