### Install Ardalis.SmartEnum.GuardClauses via NuGet Source: https://github.com/ardalis/smartenum/blob/main/src/SmartEnum.GuardClauses/README.md Use this command in the NuGet Package Manager Console to install the package. ```bash Install-Package Ardalis.SmartEnum.GuardClauses ``` -------------------------------- ### Install SmartEnum Base Package Source: https://github.com/ardalis/smartenum/blob/main/README.md Install the minimum requirements for the SmartEnum library using the NuGet Package Manager. ```csharp Install-Package Ardalis.SmartEnum ``` -------------------------------- ### Install SmartEnum Extension Packages Source: https://github.com/ardalis/smartenum/blob/main/README.md Install additional packages for serialization, AutoFixture, EF Core, Model Binding, or Dapper support as needed. ```csharp Install-Package Ardalis.SmartEnum.AutoFixture ``` ```csharp Install-Package Ardalis.SmartEnum.JsonNet ``` ```csharp Install-Package Ardalis.SmartEnum.SystemTextJson ``` ```csharp Install-Package Ardalis.SmartEnum.Utf8Json ``` ```csharp Install-Package Ardalis.SmartEnum.MessagePack ``` ```csharp Install-Package Ardalis.SmartEnum.ProtoBufNet ``` ```csharp Install-Package Ardalis.SmartEnum.EFCore ``` ```csharp Install-Package Ardalis.SmartEnum.ModelBinding ``` ```csharp Install-Package Ardalis.SmartEnum.Dapper ``` -------------------------------- ### Example: Role Enum Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates a concrete Role enumeration with string keys. ```csharp public sealed class Role : SmartEnum { public static readonly Role Administrator = new Role("adm", "Administrator"); public static readonly Role User = new Role("usr", "User"); private Role(string key, string name) : base(key, name) { } } ``` -------------------------------- ### Install Ardalis.SmartEnum.GuardClauses via .NET CLI Source: https://github.com/ardalis/smartenum/blob/main/src/SmartEnum.GuardClauses/README.md Use this command in the .NET CLI to add the package to your project. ```bash dotnet add package Ardalis.SmartEnum.GuardClauses ``` -------------------------------- ### Example: Permission FlagEnum Source: https://github.com/ardalis/smartenum/blob/main/README.md Defines a Permission SmartFlagEnum with integer flags. ```csharp public sealed class Permission : SmartFlagEnum { public static readonly Permission None = new Permission(0, nameof(None)); public static readonly Permission Read = new Permission(1, nameof(Read)); public static readonly Permission Write = new Permission(2, nameof(Write)); public static readonly Permission Delete = new Permission(4, nameof(Delete)); public static readonly Permission All = new Permission(7, nameof(All)); private Permission(int key, string name) : base(key, name) { } } ``` -------------------------------- ### Example: Status Enum Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates a concrete Status enumeration with integer keys. ```csharp public sealed class Status : SmartEnum { public static readonly Status Draft = new Status(0, nameof(Draft)); public static readonly Status Submitted = new Status(1, nameof(Submitted)); public static readonly Status Approved = new Status(2, nameof(Approved)); public static readonly Status Rejected = new Status(3, nameof(Rejected)); private Status(int key, string name) : base(key, name) { } } ``` -------------------------------- ### Using Inherited Smart Enum Properties Source: https://github.com/ardalis/smartenum/blob/main/README.md Example of using inherited properties like `BonusSize` in a parent class. ```csharp public class Manager { private ManagerType _managerType { get; set; } public string Type { get => _managerType.Name; set { if (!ManagerType.TryFromName(value, true, out var parsed)) { throw new Exception($"Invalid manager type of '{value}'"); } _managerType = parsed; } } public string BonusSize { get => _managerType.BonusSize(); set => _bonusSize_ = value; } } ``` -------------------------------- ### Access SmartFlagEnum Members by Name Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates how to retrieve SmartFlagEnum members by matching a comma-separated string of names using `FromName()`. Includes an example of using `TryFromName()` for safer retrieval and mentions the `ignoreCase` parameter. ```csharp var myFlagEnums = TestFlagEnum.FromName("One, Two"); ``` ```csharp if (TestFlagEnum.TryFromName("One, Two", out var myFlagEnums)) { // use myFlagEnums here } ``` -------------------------------- ### Access SmartFlagEnum Members by Value Source: https://github.com/ardalis/smartenum/blob/main/README.md Shows how to retrieve SmartFlagEnum members by their integer value using `FromValue()`. Includes an example of using `TryFromValue()` and notes on handling negative values and parsing exceptions. ```csharp var myFlagEnums = TestFlagEnum.FromValue(3); ``` ```csharp if (TestFlagEnum.TryFromValue(3, out var myFlagEnums)) { // use myFlagEnums here } ``` -------------------------------- ### Convert SmartFlagEnum Value to String Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates converting a SmartFlagEnum value to its string representation using `FromValueToString()`. Includes an example of using `TryFromValueToString()` and notes on handling negative values. ```csharp var myFlagEnumString = TestFlagEnum.FromValueToString(3); ``` ```csharp if (TestFlagEnum.TryFromValueToString(3, out var myFlagEnumsAsString)) { // use myFlagEnumsAsString here } ``` -------------------------------- ### List All SmartEnum Options Source: https://github.com/ardalis/smartenum/blob/main/README.md Use the static `List` property to get a collection of all available enum options. This returns an `IReadOnlyCollection` which provides efficient access to the `Count` property. ```csharp foreach (var option in TestEnum.List) Console.WriteLine(option.Name); ``` ```csharp var count = TestEnum.List.Count; ``` -------------------------------- ### SmartEnumStringComparerAttribute for Case-Insensitive String Enums Source: https://context7.com/ardalis/smartenum/llms.txt Apply [SmartEnumStringComparer] to a SmartEnum to enable case-insensitive value lookups. This example uses InvariantCultureIgnoreCase. ```csharp [SmartEnumStringComparer(StringComparison.InvariantCultureIgnoreCase)] public class ColorCode : SmartEnum { public static readonly ColorCode Red = new ColorCode("Red", "#FF0000"); public static readonly ColorCode Green = new ColorCode("Green", "#00FF00"); public static readonly ColorCode Blue = new ColorCode("Blue", "#0000FF"); protected ColorCode(string name, string value) : base(name, value) { } } ``` ```csharp // Case-insensitive value match var red1 = ColorCode.FromValue("#ff0000"); var red2 = ColorCode.FromValue("#FF0000"); Console.WriteLine(red1 == red2); // True ``` -------------------------------- ### Get enum member by key Source: https://github.com/ardalis/smartenum/blob/main/README.md Retrieve a SmartEnum member using its key. ```csharp var status = Status.FromKey(1); // status is Status.Submitted ``` -------------------------------- ### Get SmartEnum by Name Source: https://github.com/ardalis/smartenum/blob/main/README.md Retrieve an enum instance by matching its `Name` property. Use `TryFromName` for a non-throwing alternative that returns `false` if the name is not found. Both methods accept an optional `ignoreCase` parameter. ```csharp var myEnum = TestEnum.FromName("One"); ``` ```csharp if (TestEnum.TryFromName("One", out var myEnum)) { // use myEnum here } ``` -------------------------------- ### Get SmartEnum by Value Source: https://github.com/ardalis/smartenum/blob/main/README.md Retrieve an enum instance by matching its value. `TryFromValue` provides a non-throwing alternative that returns `false` if the value is not found. ```csharp var myEnum = TestEnum.FromValue(1); ``` ```csharp if (TestEnum.TryFromValue(1, out var myEnum)) { // use myEnum here } ``` -------------------------------- ### Get SmartEnum Generic Arguments Source: https://context7.com/ardalis/smartenum/llms.txt Retrieve the generic arguments `[TEnum, TValue]` from a SmartEnum type using `IsSmartEnum()` with an out parameter. This helps in understanding the enum's structure. ```csharp // Get generic arguments [TEnum, TValue] bool isSmartEnum = typeof(OrderStatus).IsSmartEnum(out Type[] args); // args[0] = typeof(OrderStatus), args[1] = typeof(int) ``` -------------------------------- ### Push NuGet Package to Repository Source: https://github.com/ardalis/smartenum/blob/main/nuget.txt After packing, push the generated .nupkg file to the NuGet repository. Replace '' with your NuGet API key and '1.0.X' with your package version. The package is typically found in the '/bin/release' folder. ```bash dotnet nuget push -s https://www.nuget.org/api/v2/package -k Ardalis.SmartEnum.1.0.X.nupkg ``` -------------------------------- ### Pack NuGet Package Source: https://github.com/ardalis/smartenum/blob/main/nuget.txt Use this command to pack your project into a NuGet package. Ensure your .csproj file is updated with the desired version and release notes. Replace '1.0.X' with your actual version number. ```bash dotnet pack -c release /p:Version=1.0.X ``` -------------------------------- ### Get enum member by name Source: https://github.com/ardalis/smartenum/blob/main/README.md Retrieve a SmartEnum member using its name (case-insensitive). ```csharp var status = Status.FromName("Approved"); // status is Status.Approved ``` -------------------------------- ### Tag Git Repository for Release Source: https://github.com/ardalis/smartenum/blob/main/nuget.txt Create a Git tag for the release version. Replace 'v1.0.X' with your tag name and 'Published 1.0.X to nuget.org' with your commit message. ```bash git tag -a v1.0.X -m "Published 1.0.X to nuget.org" ``` -------------------------------- ### Use switch statement with SmartEnum Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates using a switch statement with SmartEnum members. ```csharp Status currentStatus = Status.Submitted; switch (currentStatus) { case Status s when s == Status.Draft: Console.WriteLine("It's a draft."); break; case Status s when s == Status.Submitted: Console.WriteLine("It's submitted."); break; case Status s when s == Status.Approved: Console.WriteLine("It's approved."); break; case Status s when s == Status.Rejected: Console.WriteLine("It's rejected."); break; default: throw new ArgumentOutOfRangeException(); } ``` -------------------------------- ### Define Reservation Statuses with Transitions Source: https://github.com/ardalis/smartenum/blob/main/README.md Defines the initial status and its possible transitions to Paid or Cancelled. This serves as the base for other states. ```csharp public class ReservationStatus : SmartEnum { public static readonly ReservationStatus None = new NoneStatus(); public static readonly ReservationStatus Paid = new PaidStatus(); public static readonly ReservationStatus Cancelled = new CancelledStatus(); private ReservationStatus(string name, int value) : base(name, value) { } private sealed class NoneStatus: ReservationStatus { public NoneStatus() : base("None", 1) { } public override bool CanTransitionTo(ReservationStatus next) => next == ReservationStatus.Paid || next == ReservationStatus.Cancelled; } private sealed class PaidStatus: ReservationStatus { public PaidStatus() : base("Paid", 2) { } public override bool CanTransitionTo(ReservationStatus next) => next == ReservationStatus.Cancelled; } private sealed class CancelledStatus: ReservationStatus { public CancelledStatus() : base("Cancelled", 3) { } public override bool CanTransitionTo(ReservationStatus next) => false; } } ``` -------------------------------- ### Retrieve SmartEnum by Name Source: https://context7.com/ardalis/smartenum/llms.txt Use `FromName(string, bool)` to get an enum instance by its name. The `ignoreCase` parameter controls case sensitivity. Throws `SmartEnumNotFoundException` if the name is not found. ```csharp // Exact match (case-sensitive, default) var status = OrderStatus.FromName("Shipped"); Console.WriteLine(status.Value); // 2 // Case-insensitive match var status2 = OrderStatus.FromName("shipped", ignoreCase: true); Console.WriteLine(status2 == OrderStatus.Shipped); // True // Throws SmartEnumNotFoundException for unknown name try { var bad = OrderStatus.FromName("Unknown"); } catch (SmartEnumNotFoundException ex) { Console.WriteLine(ex.Message); // No OrderStatus with Name "Unknown" found. } ``` -------------------------------- ### SmartFlagEnum Value Handling with Explicit Combinations Source: https://github.com/ardalis/smartenum/blob/main/README.md Demonstrates how explicit combination values are handled. Values matching explicit combinations or existing flag values work, while unassigned intermediate values throw exceptions. ```csharp public class SmartFlagTestEnum : SmartFlagEnum { public static readonly SmartFlagTestEnum None = new SmartFlagTestEnum(nameof(None), 0); public static readonly SmartFlagTestEnum Card = new SmartFlagTestEnum(nameof(Card), 1); public static readonly SmartFlagTestEnum Cash = new SmartFlagTestEnum(nameof(Cash), 2); public static readonly SmartFlagTestEnum AfterPay = new SmartFlagTestEnum(nameof(AfterPay), 5); public SmartFlagTestEnum(string name, int value) : base(name, value) { } } var myFlagEnums = FromValue(3) -- Works! -and- var myFlagEnums = FromValue(5) -- Works! -but- Var myFlagEnums = FromValue(4) -- will throw an exception :( ``` -------------------------------- ### Switch on SmartEnum Instance with Pattern Matching Source: https://github.com/ardalis/smartenum/blob/main/README.md Utilize C#'s pattern matching capabilities to switch on a SmartEnum instance, including null checks and equality comparisons. ```csharp switch(testEnumVar) { case null: ... break; case var e when e.Equals(TestEnum.One): ... break; case var e when e.Equals(TestEnum.Two): ... break; case var e when e.Equals(TestEnum.Three): ... break; default: ... break; } ``` -------------------------------- ### Equality, Comparison, and Implicit Conversion Operators Source: https://context7.com/ardalis/smartenum/llms.txt Details the implementation of equality, comparison operators, and implicit/explicit conversions for SmartEnum types. ```APIDOC ## Equality, Comparison, and Implicit Conversion Operators ### Description `SmartEnum` implements `IEquatable<>` and `IComparable<>`, and provides standard comparison operators (`==`, `!=`, `<`, `<=`, `>`, `>=`). It also supports implicit conversion to its underlying value type (`TValue`) and explicit casting from `TValue`. ### Supported Operations - **Equality**: `==`, `!=` - **Comparison**: `<`, `<=`, `>`, `>=` - **Implicit Conversion**: To `TValue` - **Explicit Conversion**: From `TValue` ### Examples ```csharp var a = OrderStatus.Shipped; var b = OrderStatus.FromValue(2); Console.WriteLine(a == b); // True Console.WriteLine(a != OrderStatus.Pending); // True Console.WriteLine(a > OrderStatus.Pending); // True (value 2 > 1) // Implicit conversion to int int val = OrderStatus.Shipped; // val = 2 // Explicit cast from int var status = (SmartEnum)3; // OrderStatus.Delivered // Sorting a list var statuses = new List { OrderStatus.Cancelled, OrderStatus.Pending, OrderStatus.Shipped }; statuses.Sort(); // Pending, Shipped, Cancelled (sorted by int value 1, 2, 4) ``` ``` -------------------------------- ### Configure EF Core Conventions (EF Core 6+) Source: https://github.com/ardalis/smartenum/blob/main/README.md For EF Core 6 and later, use this to automatically configure SmartEnum value conversions within model conventions. ```csharp protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { configurationBuilder.ConfigureSmartEnum(); ... } ``` -------------------------------- ### Smart Enum State Machine Implementation Source: https://github.com/ardalis/smartenum/blob/main/README.md Implement a state machine using SmartEnum, where methods define valid transitions between states. ```csharp using Ardalis.SmartEnum; public abstract class ReservationStatus : SmartEnum { public static readonly ReservationStatus New = new NewStatus(); public static readonly ReservationStatus Accepted = new AcceptedStatus(); public static readonly ReservationStatus Paid = new PaidStatus(); public static readonly ReservationStatus Cancelled = new CancelledStatus(); private ReservationStatus(string name, int value) : base(name, value) { } public abstract bool CanTransitionTo(ReservationStatus next); private sealed class NewStatus: ReservationStatus { public NewStatus() : base("New", 0) { } public override bool CanTransitionTo(ReservationStatus next) => next == ReservationStatus.Accepted || next == ReservationStatus.Cancelled; } private sealed class AcceptedStatus: ReservationStatus { public AcceptedStatus() : base("Accepted", 1) { } ``` -------------------------------- ### Define a SmartEnum Source: https://github.com/ardalis/smartenum/blob/main/README.md Define a basic SmartEnum by inheriting from SmartEnum and providing a constructor. ```csharp public abstract class SmartEnum : IComparable, IEquatable where TEnum : SmartEnum where TKey : IEquatable { protected SmartEnum(TKey key, string name) { if (key == null) throw new ArgumentNullException(nameof(key)); if (name == null) throw new ArgumentNullException(nameof(name)); Key = key; Name = name; } public TKey Key { get; } public string Name { get; } public override string ToString() => Name; public override bool Equals(object obj) => Equals(obj as TEnum); public bool Equals(TEnum other) => other != null && Key.Equals(other.Key); public int CompareTo(TEnum other) => other == null ? 1 : Key.CompareTo(other.Key); public override int GetHashCode() => Key.GetHashCode(); public static bool operator ==(SmartEnum left, TEnum right) => left?.Equals(right) ?? Equals(right, null); public static bool operator !=(SmartEnum left, TEnum right) => !(left == right); public static bool operator <(SmartEnum left, TEnum right) => left.CompareTo(right) < 0; public static bool operator >(SmartEnum left, TEnum right) => left.CompareTo(right) > 0; public static bool operator <=(SmartEnum left, TEnum right) => left.CompareTo(right) <= 0; public static bool operator >=(SmartEnum left, TEnum right) => left.CompareTo(right) >= 0; } ``` -------------------------------- ### AutoFixture SmartEnum Support Source: https://context7.com/ardalis/smartenum/llms.txt Integrate SmartEnumCustomization with AutoFixture to enable the creation of valid, randomly selected SmartEnum instances during test data generation. ```csharp using AutoFixture; using Ardalis.SmartEnum.AutoFixture; var fixture = new Fixture() .Customize(new SmartEnumCustomization()); // AutoFixture picks a random OrderStatus from OrderStatus.List var status = fixture.Create(); Console.WriteLine(OrderStatus.List.Contains(status)); // True // Works in test data builders public class Order { public int Id { get; set; } public OrderStatus Status { get; set; } } var order = fixture.Create(); Console.WriteLine(order.Status != null); // True ``` -------------------------------- ### Configure EF Core Value Conversion Source: https://github.com/ardalis/smartenum/blob/main/README.md Use this code to configure EF Core to persist only the value of a SmartEnum to the database. Requires a parameterless constructor for the entity. ```csharp protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.Entity() .Property(p => p.PolicyStatus) .HasConversion( p => p.Value, p => PolicyStatus.FromValue(p)); } ``` -------------------------------- ### Create a concrete SmartEnum type Source: https://github.com/ardalis/smartenum/blob/main/README.md Define a concrete enumeration by inheriting from the abstract SmartEnum class and registering instances. ```csharp public abstract class SmartEnum : IComparable, IEquatable where TEnum : SmartEnum where TKey : IEquatable { // ... (previous code) private static readonly Dictionary _allMembers = new Dictionary(); protected SmartEnum(TKey key, string name) { if (key == null) throw new ArgumentNullException(nameof(key)); if (name == null) throw new ArgumentNullException(nameof(name)); Key = key; Name = name; _allMembers.Add(key, (TEnum)this); } public TKey Key { get; } public string Name { get; } public static IEnumerable List() => _allMembers.Values; public static TEnum FromKey(TKey key) => _allMembers.TryGetValue(key, out var member) ? member : throw new ArgumentException($"Invalid key: {key}"); public static TEnum FromName(string name) => _allMembers.Values.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) ?? throw new ArgumentException($"Invalid name: {name}"); public override string ToString() => Name; public override bool Equals(object obj) => Equals(obj as TEnum); public bool Equals(TEnum other) => other != null && Key.Equals(other.Key); public int CompareTo(TEnum other) => other == null ? 1 : Key.CompareTo(other.Key); public override int GetHashCode() => Key.GetHashCode(); public static bool operator ==(SmartEnum left, TEnum right) => left?.Equals(right) ?? Equals(right, null); public static bool operator !=(SmartEnum left, TEnum right) => !(left == right); public static bool operator <(SmartEnum left, TEnum right) => left.CompareTo(right) < 0; public static bool operator >(SmartEnum left, TEnum right) => left.CompareTo(right) > 0; public static bool operator <=(SmartEnum left, TEnum right) => left.CompareTo(right) <= 0; public static bool operator >=(SmartEnum left, TEnum right) => left.CompareTo(right) >= 0; } ``` -------------------------------- ### Fluent When/Then/Default Switch in C# Source: https://context7.com/ardalis/smartenum/llms.txt Provides a fluent interface for pattern-matching on enum values, replacing traditional switch statements. Chain `When` calls with `Then` actions, and use `Default` for the no-match case. Supports matching against multiple values simultaneously. ```csharp var currentStatus = OrderStatus.Shipped; currentStatus .When(OrderStatus.Pending) .Then(() => Console.WriteLine("Order is awaiting processing")) .When(OrderStatus.Shipped) .Then(() => Console.WriteLine("Order is on the way")) // ← executes .When(OrderStatus.Delivered) .Then(() => Console.WriteLine("Order has arrived")) .Default(() => Console.WriteLine("Order status unknown")); // Output: Order is on the way // Match against multiple values at once currentStatus .When(OrderStatus.Pending, OrderStatus.Shipped) .Then(() => Console.WriteLine("Order is active")) // ← executes .Default(() => Console.WriteLine("Order is closed")); ``` -------------------------------- ### Configure EF Core Value Conversion (Pre-EF Core 6) Source: https://github.com/ardalis/smartenum/blob/main/README.md For EF Core versions prior to 6, add this line to the end of your OnModelCreating method to configure SmartEnum value conversions. ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { ... modelBuilder.ConfigureSmartEnum(); } ``` -------------------------------- ### SmartFlagEnum 'All' Value Handling Source: https://github.com/ardalis/smartenum/blob/main/README.md Defines and utilizes the special '-1' value for an 'All' flag. This returns all defined flag values (excluding 0) unless an explicit '-1' combination value is defined. ```csharp public class SmartFlagTestEnum : SmartFlagEnum { public static readonly SmartFlagTestEnum All = new SmartFlagTestEnum(nameof(All), -1); public static readonly SmartFlagTestEnum None = new SmartFlagTestEnum(nameof(None), 0); public static readonly SmartFlagTestEnum Card = new SmartFlagTestEnum(nameof(Card), 1); ``` -------------------------------- ### TryFromName: Non-throwing Name Lookup in C# Source: https://context7.com/ardalis/smartenum/llms.txt Use TryFromName for safe, non-throwing lookups by name. It returns true and populates the result on success, or false on failure. Supports case-insensitive matching. ```csharp if (OrderStatus.TryFromName("Delivered", out var status)) { Console.WriteLine($"Found: {status.Name} ({status.Value})"); // Found: Delivered (3) } // Case-insensitive try if (OrderStatus.TryFromName("cancelled", ignoreCase: true, out var cancelled)) { Console.WriteLine(cancelled == OrderStatus.Cancelled); // True } // Returns false without throwing bool found = OrderStatus.TryFromName("Ghost", out var _); Console.WriteLine(found); // False ``` -------------------------------- ### Define SmartEnum with Behavior Source: https://context7.com/ardalis/smartenum/llms.txt Abstract SmartEnum classes can define behavior. Concrete implementations inherit and provide specific logic, such as bonus calculations. ```csharp // SmartEnum with behavior via inheritance public abstract class EmployeeType : SmartEnum { 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; } } // Usage Console.WriteLine(EmployeeType.Manager.BonusSize); // 10000 ``` -------------------------------- ### Define SmartFlagEnum Values Source: https://github.com/ardalis/smartenum/blob/main/README.md Shows how to define static readonly values for a SmartFlagEnum. Ensure the base constructor is called with the name and value. ```csharp public static readonly SmartFlagTestEnum Cash = new SmartFlagTestEnum(nameof(Cash), 2); public static readonly SmartFlagTestEnum Bpay = new SmartFlagTestEnum(nameof(Bpay), 4); public static readonly SmartFlagTestEnum Paypal = new SmartFlagTestEnum(nameof(Paypal), 8); public static readonly SmartFlagTestEnum BankTransfer = new SmartFlagTestEnum(nameof(BankTransfer), 16); public SmartFlagTestEnum(string name, int value) : base(name, value) { } } ``` -------------------------------- ### Push Git Tags Source: https://github.com/ardalis/smartenum/blob/main/nuget.txt Push all local tags to the remote repository to ensure your tags are available remotely. ```bash git push --follow-tags ``` -------------------------------- ### Comparing Smart Enums Source: https://github.com/ardalis/smartenum/blob/main/README.md Smart enum comparison is based on their Value, not their Name. ```csharp TestEnum.One.Equals(TestEnum.One); // returns true TestEnum.One.Equals(TestEnum.Three); // returns false TestEnum.Three.Equals(TestEnum.AnotherThree); // returns true ``` -------------------------------- ### System.Text.Json Serialization by Name Source: https://github.com/ardalis/smartenum/blob/main/README.md Use this attribute to serialize SmartEnum properties by their Name using System.Text.Json. ```csharp public class TestClass { [JsonConverter(typeof(SmartEnumNameConverter))] public TestEnum Property { get; set; } } ``` -------------------------------- ### List all enum members Source: https://github.com/ardalis/smartenum/blob/main/README.md Retrieve a list of all defined members for a SmartEnum type. ```csharp var allStatuses = Status.List(); // Returns Status.Draft, Status.Submitted, Status.Approved, Status.Rejected ``` -------------------------------- ### Define and Use SmartFlagEnum for Employee Types Source: https://github.com/ardalis/smartenum/blob/main/README.md Defines a custom SmartFlagEnum for employee types, including specific bonus sizes for each type. Demonstrates how to retrieve and display information about enum members based on their values. ```csharp public abstract class EmployeeType : SmartFlagEnum { public static readonly EmployeeType Director = new DirectorType(); 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 DirectorType : EmployeeType { public DirectorType() : base("Director", 1) { } public override decimal BonusSize => 100_000m; } private sealed class ManagerType : EmployeeType { public ManagerType() : base("Manager", 2) { } public override decimal BonusSize => 10_000m; } private sealed class AssistantType : EmployeeType { public AssistantType() : base("Assistant", 4) { } public override decimal BonusSize => 1_000m; } } public class SmartFlagEnumUsageExample { public void UseSmartFlagEnumOne() { var result = EmployeeType.FromValue(3).ToList(); var outputString = ""; foreach (var employeeType in result) { outputString += $"{employeeType.Name} earns ${employeeType.BonusSize} bonus this year.\n"; } => "Director earns $100000 bonus this year.\n" "Manager earns $10000 bonus this year.\n" } public void UseSmartFlagEnumTwo() { EmployeeType.FromValueToString(-1) => "Director, Manager, Assistant" } public void UseSmartFlagEnumTwo() { EmployeeType.FromValueToString(EmployeeType.Assistant | EmployeeType.Director) => "Director, Assistant" } } ``` -------------------------------- ### Define SmartFlagEnum with Power-of-Two Values Source: https://github.com/ardalis/smartenum/blob/main/README.md Define a SmartFlagEnum where each flag value is a power of two. This is the default and recommended behavior to ensure correct flag operations. ```csharp public class SmartFlagTestEnum : SmartFlagEnum { public static readonly SmartFlagTestEnum None = new SmartFlagTestEnum(nameof(None), 0); public static readonly SmartFlagTestEnum Card = new SmartFlagTestEnum(nameof(Card), 1); public static readonly SmartFlagTestEnum Cash = new SmartFlagTestEnum(nameof(Cash), 2); public static readonly SmartFlagTestEnum Bpay = new SmartFlagTestEnum(nameof(Bpay), 4); public static readonly SmartFlagTestEnum Paypal = new SmartFlagTestEnum(nameof(Paypal), 8); public static readonly SmartFlagTestEnum BankTransfer = new SmartFlagTestEnum(nameof(BankTransfer), 16); public SmartFlagTestEnum(string name, int value) : base(name, value) { } } ``` -------------------------------- ### Display SmartEnum using ToString() Source: https://github.com/ardalis/smartenum/blob/main/README.md The `ToString()` override provides a convenient way to display the enum's name. ```csharp Console.WriteLine(TestEnum.One); // One ``` -------------------------------- ### Define SmartFlagEnum with AllowNegativeInput Attribute Source: https://github.com/ardalis/smartenum/blob/main/README.md Illustrates defining a `SmartFlagEnum` with the `AllowNegativeInput` attribute, which modifies the behavior for handling negative values passed to `FromValue()`. ```csharp [AllowNegativeInput] public class SmartFlagTestEnum : SmartFlagEnum { public static readonly SmartFlagTestEnum None = new SmartFlagTestEnum(nameof(None), 0); public static readonly SmartFlagTestEnum Card = new SmartFlagTestEnum(nameof(Card), 1); public SmartFlagTestEnum(string name, int value) : base(name, value) { } } ``` -------------------------------- ### Switch on SmartEnum Name Source: https://github.com/ardalis/smartenum/blob/main/README.md Perform conditional logic based on the `Name` property of a SmartEnum instance using a standard switch statement. ```csharp switch(testEnumVar.Name) { case nameof(TestEnum.One): ... break; case nameof(TestEnum.Two): ... break; case nameof(TestEnum.Three): ... break; default: ... break; } ``` -------------------------------- ### System.Text.Json Serialization by Value Source: https://github.com/ardalis/smartenum/blob/main/README.md Use this attribute to serialize SmartEnum properties by their Value using System.Text.Json. ```csharp public class TestClass { [JsonConverter(typeof(SmartEnumValueConverter))] public TestEnum Property { get; set; } } ``` -------------------------------- ### Map SmartFlagEnum with Dapper Source: https://github.com/ardalis/smartenum/blob/main/README.md Configure Dapper to map SmartFlagEnum types by registering a type handler. ```csharp public class PermissionHandler : SqlMapper { public override void SetValue(IDbDataParameter parameter, Permission value) { parameter.Value = value.Key; } } // Usage: SqlMapper.AddTypeHandler(new PermissionHandler()); // Then you can query: var permissions = connection.QuerySingle("SELECT Key FROM PermissionTable WHERE Id = 1"); ``` -------------------------------- ### Validate Input Against SmartEnum with Guard Clauses Source: https://context7.com/ardalis/smartenum/llms.txt Employ `Guard.Against.SmartEnumOutOfRange()` to validate an input value against a SmartEnum. It returns the matched instance or throws a `SmartEnumNotFoundException` if the value is invalid. ```csharp using Ardalis.GuardClauses; using Ardalis.SmartEnum.GuardClauses; public OrderStatus ProcessOrder(int statusCode) { // Throws SmartEnumNotFoundException if statusCode is not a valid OrderStatus value var status = Guard.Against.SmartEnumOutOfRange(statusCode); return status; } ``` ```csharp // With custom message var status2 = Guard.Against.SmartEnumOutOfRange( input: 2, message: "Provided status code is not recognized."); // Returns OrderStatus.Shipped ``` ```csharp // With custom exception factory var status3 = Guard.Against.SmartEnumOutOfRange( input: 99, exceptionCreator: () => new ArgumentException("Invalid order status")); // Throws ArgumentException ``` -------------------------------- ### Define Integer-Backed SmartEnum Source: https://context7.com/ardalis/smartenum/llms.txt Inherit from SmartEnum to create an integer-backed enumeration. Declare members as public static readonly fields. ```csharp using Ardalis.SmartEnum; // Integer-backed SmartEnum (most common) public sealed class OrderStatus : SmartEnum { public static readonly OrderStatus Pending = new OrderStatus(nameof(Pending), 1); public static readonly OrderStatus Shipped = new OrderStatus(nameof(Shipped), 2); public static readonly OrderStatus Delivered = new OrderStatus(nameof(Delivered), 3); public static readonly OrderStatus Cancelled = new OrderStatus(nameof(Cancelled), 4); private OrderStatus(string name, int value) : base(name, value) { } } ``` -------------------------------- ### AutoFixture Customization for SmartEnum Source: https://github.com/ardalis/smartenum/blob/main/README.md Integrate SmartEnum with AutoFixture by adding this customization to your fixture. This ensures that new instances of SmartEnum are created correctly. ```csharp var fixture = new Fixture() .Customize(new SmartEnumCustomization()); var smartEnum = fixture.Create(); ``` -------------------------------- ### Map SmartEnum with Dapper Source: https://github.com/ardalis/smartenum/blob/main/README.md Configure Dapper to map SmartEnum types by registering a type handler. ```csharp public class StatusHandler : SqlMapper { public override void SetValue(IDbDataParameter parameter, Status value) { parameter.Value = value.Key; } } // Usage: SqlMapper.AddTypeHandler(new StatusHandler()); // Then you can query: var status = connection.QuerySingle("SELECT Key FROM StatusTable WHERE Id = 1"); ``` -------------------------------- ### Persist SmartFlagEnum with EF Core Source: https://github.com/ardalis/smartenum/blob/main/README.md Configure EF Core to use SmartFlagEnum types by providing a ValueConverter. ```csharp public class MyDbContext : DbContext { public DbSet Documents { get; set; } public MyDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(e => e.Permissions) .HasConversion(v => v.Key, v => Permission.FromKey(v)); } } public class Document { public int Id { get; set; } public Permission Permissions { get; set; } } ``` -------------------------------- ### Fluent Interface for SmartEnum Switching Source: https://github.com/ardalis/smartenum/blob/main/README.md Use the fluent interface provided by SmartEnum for a more readable way to handle conditional logic based on enum values. Note that this interface may have a slight performance overhead compared to traditional switch statements. ```csharp testEnumVar .When(TestEnum.One).Then(() => ... ) .When(TestEnum.Two).Then(() => ... ) .When(TestEnum.Three).Then(() => ... ) .Default( ... ); ``` -------------------------------- ### Add Behavior to Smart Enums via Inheritance Source: https://github.com/ardalis/smartenum/blob/main/README.md Inherit from SmartEnum to add custom properties and methods, avoiding switch statements. ```csharp using Ardalis.SmartEnum; public abstract class EmployeeType : SmartEnum { 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; } } ``` -------------------------------- ### Define a SmartFlagEnum Source: https://github.com/ardalis/smartenum/blob/main/README.md Define a SmartFlagEnum by inheriting from SmartFlagEnum and using bitwise flags. ```csharp public abstract class SmartFlagEnum : SmartEnum, IBitwise where TEnum : SmartFlagEnum where TKey : IEquatable { protected SmartFlagEnum(TKey key, string name) : base(key, name) { } public static TEnum operator |(SmartFlagEnum left, TEnum right) => FromKey(BitwiseOr(left.Key, right.Key)); public static TEnum operator &(SmartFlagEnum left, TEnum right) => FromKey(BitwiseAnd(left.Key, right.Key)); public static TEnum operator ^(SmartFlagEnum left, TEnum right) => FromKey(BitwiseXor(left.Key, right.Key)); public static TEnum operator ~(SmartFlagEnum left) => FromKey(BitwiseNot(left.Key)); public static bool operator true(SmartFlagEnum left) => !Equals(left.Key, default(TKey)); public static bool operator false(SmartFlagEnum left) => Equals(left.Key, default(TKey)); public static TEnum operator -(SmartFlagEnum left, TEnum right) => FromKey(BitwiseAnd(left.Key, BitwiseNot(right.Key))); public static TEnum operator +(SmartFlagEnum left, TEnum right) => FromKey(BitwiseOr(left.Key, right.Key)); public static bool HasFlag(TEnum value, TEnum flag) => (value & flag) == flag; private static TKey BitwiseOr(TKey left, TKey right) => throw new NotImplementedException(); private static TKey BitwiseAnd(TKey left, TKey right) => throw new NotImplementedException(); private static TKey BitwiseXor(TKey left, TKey right) => throw new NotImplementedException(); private static TKey BitwiseNot(TKey left) => throw new NotImplementedException(); } ``` -------------------------------- ### Fluent Switch: When(...).Then(...).Default(...) Source: https://context7.com/ardalis/smartenum/llms.txt Enables pattern matching on enum values using a fluent interface, allowing for chained conditional execution without traditional switch statements. ```APIDOC ## Fluent Switch: When(...).Then(...).Default(...) ### Description A fluent interface for pattern-matching on enum values without switch statements. Each `When` call is chained to a `Then` action; `Default` handles the no-match case. ### Usage Chain `When` calls for specific enum values, each followed by a `Then` action. Use `Default` to specify an action when no `When` condition matches. ### Examples ```csharp var currentStatus = OrderStatus.Shipped; currentStatus .When(OrderStatus.Pending) .Then(() => Console.WriteLine("Order is awaiting processing")) .When(OrderStatus.Shipped) .Then(() => Console.WriteLine("Order is on the way")) // ← executes .When(OrderStatus.Delivered) .Then(() => Console.WriteLine("Order has arrived")) .Default(() => Console.WriteLine("Order status unknown")); // Output: Order is on the way // Match against multiple values at once currentStatus .When(OrderStatus.Pending, OrderStatus.Shipped) .Then(() => Console.WriteLine("Order is active")) // ← executes .Default(() => Console.WriteLine("Order is closed")); ``` ``` -------------------------------- ### Serialize SmartEnum to JSON Source: https://github.com/ardalis/smartenum/blob/main/README.md Use the SmartEnumBinder to automatically handle JSON serialization and deserialization. ```csharp public class Product { public int Id { get; set; } public Status Status { get; set; } } // Usage: var product = new Product { Id = 1, Status = Status.Approved }; var json = JsonSerializer.Serialize(product); // json will be: {"Id":1,"Status":{"Key":2,"Name":"Approved"}} var deserializedProduct = JsonSerializer.Deserialize(json); // deserializedProduct.Status will be Status.Approved ``` -------------------------------- ### Persist SmartEnum with EF Core Source: https://github.com/ardalis/smartenum/blob/main/README.md Configure EF Core to use SmartEnum types by providing a ValueConverter. ```csharp public class MyDbContext : DbContext { public DbSet Products { get; set; } public MyDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(e => e.Status) .HasConversion(v => v.Key, v => Status.FromKey(v)); } } public class Product { public int Id { get; set; } public Status Status { get; set; } } ``` -------------------------------- ### TryFromValue: Non-throwing Value Lookup in C# Source: https://context7.com/ardalis/smartenum/llms.txt Use TryFromValue for safe, non-throwing lookups by underlying value. It returns true and populates the result on success, or false on failure. ```csharp if (OrderStatus.TryFromValue(3, out var status)) { Console.WriteLine(status.Name); // Delivered } bool found = OrderStatus.TryFromValue(999, out var _); Console.WriteLine(found); // False ``` -------------------------------- ### Combine SmartFlagEnum values Source: https://github.com/ardalis/smartenum/blob/main/README.md Use the bitwise OR operator to combine SmartFlagEnum values. ```csharp var permissions = Permission.Read | Permission.Write; // permissions is now a combination of Read and Write ``` -------------------------------- ### SmartFlagEnum - Bitwise Flag Enumerations Source: https://context7.com/ardalis/smartenum/llms.txt Defines a SmartFlagEnum for bitwise operations. Values must be powers of two. Use FromValue to retrieve matching flags. ```csharp using Ardalis.SmartEnum; public class PaymentMethod : SmartFlagEnum { public static readonly PaymentMethod None = new PaymentMethod(nameof(None), 0); public static readonly PaymentMethod Card = new PaymentMethod(nameof(Card), 1); public static readonly PaymentMethod Cash = new PaymentMethod(nameof(Cash), 2); public static readonly PaymentMethod BankTransfer = new PaymentMethod(nameof(BankTransfer), 4); public static readonly PaymentMethod PayPal = new PaymentMethod(nameof(PayPal), 8); public PaymentMethod(string name, int value) : base(name, value) { } } ``` ```csharp // FromValue returns all matching flags var methods = PaymentMethod.FromValue(3).ToList(); // methods = [Card, Cash] ``` ```csharp // FromName with comma-separated names var methods2 = PaymentMethod.FromName("Card, BankTransfer").ToList(); // methods2 = [Card, BankTransfer] ``` ```csharp // FromValueToString — returns comma-separated names string label = PaymentMethod.FromValueToString(5); // "Card, BankTransfer" ``` ```csharp // Bitwise OR with implicit int conversion var combo = PaymentMethod.FromValue(PaymentMethod.Card | PaymentMethod.PayPal).ToList(); // combo = [Card, PayPal] ``` ```csharp // TryFromValue — non-throwing if (PaymentMethod.TryFromValue(6, out var result)) { Console.WriteLine(string.Join(", ", result.Select(r => r.Name))); // Cash, BankTransfer } ``` ```csharp // -1 returns all non-zero values var all = PaymentMethod.FromValue(-1).ToList(); // all = [Card, Cash, BankTransfer, PayPal] ``` -------------------------------- ### Configure SmartEnum Converters in EF Core Source: https://context7.com/ardalis/smartenum/llms.txt Integrate SmartEnum with EF Core by calling `configurationBuilder.ConfigureSmartEnum()` in `ConfigureConventions` (EF Core 6+) or `modelBuilder.ConfigureSmartEnum()` in `OnModelCreating` (EF Core < 6). This automatically registers converters for SmartEnum properties. ```csharp using Microsoft.EntityFrameworkCore; using SmartEnum.EFCore; public class Order { public int Id { get; set; } public OrderStatus Status { get; set; } // SmartEnum property } public class AppDbContext : DbContext { public DbSet Orders { get; set; } // EF Core 6+ (pre-convention configuration) protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { configurationBuilder.ConfigureSmartEnum(); } // EF Core < 6 — call in OnModelCreating protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ConfigureSmartEnum(); // Manual per-property configuration is also supported: modelBuilder.Entity() .Property(o => o.Status) .HasConversion(s => s.Value, v => OrderStatus.FromValue(v)); } } ``` -------------------------------- ### Serialize SmartFlagEnum to JSON Source: https://github.com/ardalis/smartenum/blob/main/README.md Use the SmartFlagEnumBinder to automatically handle JSON serialization and deserialization for flag enums. ```csharp public class Document { public int Id { get; set; } public Permission Permissions { get; set; } } // Usage: var document = new Document { Id = 1, Permissions = Permission.Read | Permission.Write }; var json = JsonSerializer.Serialize(document); // json will be: {"Id":1,"Permissions":{"Key":3,"Name":"Read, Write"}} var deserializedDocument = JsonSerializer.Deserialize(json); // deserializedDocument.Permissions will be Permission.Read | Permission.Write ```