这完全取决于您对枚举类型的使用目的。
If you are trying to stop your developers from passing magic numbers into your operations and you want to keep the data referential integrity intact with your DB then, YES! Use T4-Templates (using your ORM) to go to your MeasurementUnitTypes table and generate a enum with the ID, Name and Description columns matching the enum’ int, Enum_Name and Description Attribute (nice approach for additional field\data to enum @danijels) as suggested above. If you add a new Measurement Type to your MeasurementUnitTypes table you can just right click and run the T4-Template and the enum code is generated for that new row added in the table. I don’t like hard-coded data in my application that doesnt link to my DB hence the mention of the T4-Template approach. It is not extensible otherwise...what if some other external system wants to retrieve our Measurement Criteria used in our system, then it is hard-coded in the system and you can't expose it to the client via a service. That left there.
If the purpose is not data related and you have some logic assigned to a specific enum then NO! this violates the SOLID (Open close principle) as you would somewhere in your application apply a switch or bunch of Ifs to action the logic per enum, ALSO if you did it REALLY bad these switches or Ifs are all over the show....good luck adding a new enum... so it is not open for extension and closed for modification as you need to modify existing code, as per the SOLID principle.
If your choice is 2 then I suggest then to replace your enum with the following using the example from @danijels comment:
public interface IMeasurementUnitType
{
int ID { get; }
string Description { get; }
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创建类的实例来填充我们的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,但我真的很喜欢枚举,但是当您尝试使用枚举分离逻辑时,它是一个强烈的反模式。
欢迎评论,
switch
与枚举本身并不是不好的。有时它是必要的,比如在提到的工厂中。 - AndreyDictionary<myEnum,Action<> >
->actionDictionary[enumValue]();
- Pasi Savolainen