Używanie klas wyliczenia zamiast typów wyliczenia

Napiwek

Ta zawartość jest fragmentem książki eBook, architektury mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET dostępnych na platformie .NET Docs lub jako bezpłatnego pliku PDF, który można odczytać w trybie offline.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Wyliczenia (lub typy wyliczeniowe w skrócie) to cienka otoka języka wokół typu całkowitego. Możesz ograniczyć ich użycie do, gdy przechowujesz jedną wartość z zamkniętego zestawu wartości. Klasyfikacja oparta na rozmiarach (małych, średnich, dużych) jest dobrym przykładem. Używanie wyliczenia do przepływu sterowania lub bardziej niezawodnych abstrakcji może być zapachem kodu. Ten typ użycia prowadzi do kruchego kodu z wieloma instrukcjami przepływu sterowania sprawdzającymi wartości wyliczenia.

Zamiast tego można utworzyć klasy Wyliczenia, które umożliwiają korzystanie ze wszystkich zaawansowanych funkcji języka obiektowego.

Jednak nie jest to temat krytyczny, a w wielu przypadkach dla uproszczenia można nadal używać zwykłych typów wyliczenia, jeśli są to twoje preferencje. Użycie klas wyliczenia jest bardziej związane z pojęciami związanymi z działalnością biznesową.

Implementowanie klasy bazowej Wyliczenia

Mikrousługi porządkowania w eShopOnContainers udostępnia przykładową implementację klasy bazowej Wyliczenia, jak pokazano w poniższym przykładzie:

public abstract class Enumeration : IComparable
{
    public string Name { get; private set; }

    public int Id { get; private set; }

    protected Enumeration(int id, string name) => (Id, Name) = (id, name);

    public override string ToString() => Name;

    public static IEnumerable<T> GetAll<T>() where T : Enumeration =>
        typeof(T).GetFields(BindingFlags.Public |
                            BindingFlags.Static |
                            BindingFlags.DeclaredOnly)
                 .Select(f => f.GetValue(null))
                 .Cast<T>();

    public override bool Equals(object obj)
    {
        if (obj is not Enumeration otherValue)
        {
            return false;
        }

        var typeMatches = GetType().Equals(obj.GetType());
        var valueMatches = Id.Equals(otherValue.Id);

        return typeMatches && valueMatches;
    }

    public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id);

    // Other utility methods ...
}

Tej klasy można użyć jako typu w dowolnym obiekcie jednostki lub wartości, tak jak w przypadku następującej CardType klasy : Enumeration

public class CardType
    : Enumeration
{
    public static CardType Amex = new(1, nameof(Amex));
    public static CardType Visa = new(2, nameof(Visa));
    public static CardType MasterCard = new(3, nameof(MasterCard));

    public CardType(int id, string name)
        : base(id, name)
    {
    }
}

Dodatkowe zasoby