Все зависит от того, что вы пытаетесь сделать с перечислением.
Если вы пытаетесь помешать вашим разработчикам передавать магические числа в свои операции и хотите сохранить целостность данных в своей БД, ДА! Используйте T4-шаблоны (используя ORM), чтобы перейти к таблице MeasurementUnitTypes и сгенерировать перечисление со столбцами ID, Name и Description, соответствующими enum 'int, Enum_Name и Description Attribute (хороший подход для дополнительных полей \ данных для перечисления @danijels) как было предложено выше. Если вы добавляете новый тип измерения в таблицу MeasurementUnitTypes, вы можете просто щелкнуть правой кнопкой мыши и запустить T4-Template, и код перечисления будет сгенерирован для этой новой строки, добавленной в таблицу. Мне не нравятся жестко закодированные данные в моем приложении, которые не связаны с моей БД, поэтому упоминается подход T4-Template. В противном случае он не может быть расширен ... что, если какая-то другая внешняя система хочет получить наши критерии измерения, используемые в нашей системе, тогда он жестко запрограммирован в системе, и вы не можете предоставить его клиенту через службу. Это осталось там.
Если цель не связана с данными и у вас есть логика, назначенная конкретному перечислению, тогда НЕТ! это нарушает SOLID (принцип открытого закрытия), как если бы вы где-то в своем приложении применили переключатель или группу Ifs для действия логики для каждого перечисления, ТАКЖЕ, если вы сделали это ДЕЙСТВИТЕЛЬНО плохо, эти переключатели или Ifs повсюду .... удачи в добавлении нового перечисления ... чтобы оно не было открыто для расширения и закрыто для модификации, поскольку вам необходимо изменить существующий код в соответствии с принципом SOLID.
Если ваш выбор - 2, я предлагаю заменить ваше перечисление следующим, используя пример из комментария @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, а НЕ сам интерфейс. Теперь мы можем использовать Activator для создания экземпляров классов для заполнения наших элементов управления пользовательского интерфейса:
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, но мне очень нравятся перечисления, но я чувствую, что когда вы пытаетесь разделить логику с помощью перечислений, это СИЛЬНЫЙ анти-шаблон.
комментарии приветствуются,
person
Ernest Gunning
schedule
28.09.2018
switch
против enum само по себе неплохо. иногда это необходимо, например на указанном заводе. - person Andrey   schedule 12.10.2010