Всичко зависи от това какво се опитвате да направите с enum.
Ако се опитвате да спрете вашите разработчици да предават магически числа във вашите операции и искате да запазите референтната цялост на данните непокътната с вашата DB, тогава ДА! Използвайте T4-Templates (използвайки вашия ORM), за да отидете до вашата таблица MeasurementUnitTypes и да генерирате enum с колони ID, Name и Description, съответстващи на enum' int, Enum_Name и Description Attribute (хубав подход за допълнително поле\данни към enum @danijels) както е предложено по-горе. Ако добавите нов тип измерване към вашата таблица MeasurementUnitTypes, можете просто да щракнете с десния бутон и да изпълните T4-Template и enum кодът се генерира за този нов ред, добавен в таблицата. Не харесвам твърдо кодирани данни в моето приложение, които не се свързват с моята база данни, следователно споменаването на подхода T4-Template. Не е разширяем по друг начин... какво ще стане, ако друга външна система иска да извлече нашите критерии за измерване, използвани в нашата система, тогава тя е твърдо кодирана в системата и не можете да я изложите на клиента чрез услуга. Това остана там.
Ако целта не е свързана с данни и имате някаква логика, присвоена на конкретно преброяване, тогава НЕ! това нарушава SOLID (принцип за отваряне и затваряне), тъй като някъде във вашето приложение бихте приложили превключвател или куп Ifs, за да действате по логиката за преброяване, СЪЩО ТО, ако сте го направили НАИСТИНА лошо, тези превключватели или Ifs са навсякъде в шоуто.... успех с добавянето на нов enum... така че не е отворен за разширение и затворен за модификация, тъй като трябва да модифицирате съществуващия код, според принципа SOLID.
Ако вашият избор е 2, предлагам да замените enum със следното, като използвате примера от коментара на @danijels:
public interface IMeasurementUnitType
{
int ID { get; }
string Description { get; }
// Just added to simulate a action needed in the system
string GetPrintMessage(int size);
}
Горният код дефинира интерфейса (договор за код), към който трябва да се придържа всяко измерване. Сега нека дефинираме измерването на процент и пиксел:
public class PixelsMeasurementUnitType : IMeasurementUnitType
{
public int ID => 1;
public string Description => "Pixel";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} pixels of the total screen size";
}
}
public class PercentMeasurementUnitType : IMeasurementUnitType
{
public int ID => 2;
public string Description => "Persentage";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} persent of total screen size (100)";
}
}
И така, дефинирахме два типа, бихме ги използвали в кода, както следва:
var listOfMeasurmentTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IMeasurementUnitType).IsAssignableFrom(p)
&& !p.IsInterface)
.ToList();
Тук грабваме всички ТИПОВЕ, които разширяват интерфейса IMeasurementUnitType, а НЕ самия интерфейс. Сега можем да използваме активатора, за да създадем екземпляри на класовете, за да попълним нашите UI контроли:
public IEnumerable<IMeasurementUnitType> GetInstantiatedClassesFromTypes(List<Type> types)
{
foreach (var type in types)
{
yield return (IMeasurementUnitType)Activator.CreateInstance(type);
}
}
Можете да промените кода по-горе, за да бъде общ за всеки тип, И СЕГА животът се случва и клиентът дава нов тип мерна единица, наречен Point, като ново изискване, не е необходимо да ПРОМЕНЯ НИКАКЪВ код, просто добавя новия тип (разширете кодът НЕ се променя). Новият тип автоматично ще бъде взет в приложението.
public class PointMeasurementUnitType : IMeasurementUnitType
{
public int ID => 3;
public string Description => "Point";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} points of total screen size";
}
}
добра идея би била да кеширате вашите типове за ползи от производителността при стартиране на вашето приложение или да опитате да използвате DI контейнер по ваш избор.
Освен това може да се твърди, че някъде във вашето приложение ще трябва да правите разлика между типовете и аз съм съгласен, но искате да запазите ябълките с ябълки. Така че опитайте, доколкото е възможно, да приложите същия принцип, използван за тези типове. Ако този тип се използва в някакъв клас графичен процесор (например), тогава имайте IGraphicsProcessor и вашите конкретни класове, които правят разлика между тези типове, например PersentageAndPixelGraphicsProcessor (който се простира от IGraphicsProcessor) или ако разграничава само един тип, наречете го PersentageGraphicsProcessor.
Съжалявам за ОГРОМНОТО SA, но аз наистина харесвам enum, но чувствам, че когато се опитвате да разделите логиката с помощта на enum, това е СИЛЕН анти-модел.
коментарите са добре дошли,
person
Ernest Gunning
schedule
28.09.2018
switch
срещу enum не е лошо само по себе си. понякога е необходимо, например в споменатата фабрика. - person Andrey   schedule 12.10.2010