Last active
January 2, 2026 08:41
-
-
Save heldercsousa/88d8b056a96f67a7cef69fc9edd45f73 to your computer and use it in GitHub Desktop.
C# Smart Enum Pattern - Part 3: Advanced generic class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public interface ISmartEnumValue | |
| { | |
| int Id { get; } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public record OrderStatusValue(int Id, string Description) : ISmartEnumValue; | |
| public class OrderStatus : SmartEnum<OrderStatusValue, OrderStatus> | |
| { | |
| public static readonly OrderStatusValue Pending = Register(new(1, "Pending")); | |
| public static readonly OrderStatusValue Shipped = Register(new(2, "Shipped")); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public record ProductStatusValue(int Id, string Description) : ISmartEnumValue; | |
| public class ProductStatus : SmartEnum<ProductStatusValue, ProductStatus> | |
| { | |
| public static readonly ProductStatusValue Pending = Register(new(1, "Pending")); | |
| public static readonly ProductStatusValue Available = Register(new(2, "Available")); | |
| public static readonly ProductStatusValue OutOfStock = Register(new(3, "Out of Stock")); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class Program | |
| { | |
| public static void Main() | |
| { | |
| // Initialize once at startup (e.g., Program.cs) | |
| ProductStatus.Initialize(); | |
| // Example 1: Strict access (Expects ID to exist) | |
| var status = ProductStatus.Get(1); | |
| Console.WriteLine($"Expected to exist ProductStatus ID 1 : {status.Description}"); | |
| // Example 2: Check if exists | |
| if (ProductStatus.Exists(2)) | |
| { | |
| var found = ProductStatus.Get(2); | |
| Console.WriteLine($"\nFound product status (Get): {found.Description}"); | |
| } | |
| // Example 3: Safe access with null check | |
| var maybeStatus = ProductStatus.GetOrDefault(99); | |
| if (maybeStatus == null) | |
| { | |
| Console.WriteLine("\nProduct status ID 99 does not exist"); | |
| } | |
| // Example 4: Pattern matching for clean branching | |
| if (ProductStatus.TryGet(2, out var foundStatus)) | |
| { | |
| Console.WriteLine($"\nFound Product status (TryGet): {foundStatus?.Description}"); | |
| } | |
| Console.WriteLine("\nAll product statuses:"); | |
| foreach (var s in ProductStatus.GetAll()) | |
| { | |
| Console.WriteLine($" - {s})"); | |
| } | |
| OrderStatus.Initialize(); | |
| if (OrderStatus.Exists(1)) | |
| { | |
| var orderStatus = OrderStatus.Get(1); | |
| Console.WriteLine($"\nFound order status: {status.Description}"); | |
| } | |
| Console.WriteLine("\nAll order statuses:"); | |
| foreach (var s in OrderStatus.GetAll()) | |
| { | |
| Console.WriteLine($" - {s.Id}-{s.Description}"); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Runtime.CompilerServices; | |
| public abstract class SmartEnum<TValue, TSelf> | |
| where TValue : class, ISmartEnumValue | |
| where TSelf : SmartEnum<TValue, TSelf> | |
| { | |
| private static readonly Dictionary<int, TValue> _lookup = new(); | |
| protected static TValue Register(TValue value) | |
| { | |
| _lookup[value.Id] = value; | |
| return value; | |
| } | |
| public static void Initialize() | |
| { | |
| RuntimeHelpers.RunClassConstructor(typeof(TSelf).TypeHandle); | |
| } | |
| public static TValue Get(int id) | |
| { | |
| if (_lookup.TryGetValue(id, out var value)) | |
| return value; | |
| throw new KeyNotFoundException( | |
| $"Value with ID {id} not found in {typeof(TSelf).Name}"); | |
| } | |
| public static TValue? GetOrDefault(int id) => _lookup.GetValueOrDefault(id); | |
| public static bool TryGet(int id, out TValue? value) | |
| { | |
| return _lookup.TryGetValue(id, out value); | |
| } | |
| public static bool Exists(int id) => _lookup.ContainsKey(id); | |
| public static IEnumerable<TValue> GetAll() => _lookup.Values; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment