Multiple choice enum
本文关键字:enum choice Multiple | 更新日期: 2023-09-27 18:19:18
我最近开始一个项目,我有一个问题。
假设我正在处理一类Person
,并且一个人可能患有他遇到的一种(或多种)疾病。所以我创建了一个enum:
public enum diseases{headache,throat,bruise,gunshot,none}; // enum containing all the diseases
public diseases disease;
在代码中,我设置了一个特定的disease
给那个人,它工作得很好。
问题是,在我的项目中可能有一个点,一个人可能有两种疾病。这就是我的问题:
- 在这里使用enum是最好的选择吗?我希望我的代码是有组织的和容易理解的,这是使用枚举的主要原因。
- 如果使用枚举是一个很好的选择,我已经设法将此枚举与位标志(使用
[System.Flags]
)结合起来,所以当时间到来时,我可以检查包含两个不同值的disease
从枚举。这是一个好方法吗? - 如果使用enum是一个很好的选择,我应该从
diseases
(就像我创建disease
)创建第二个属性,并避免使用位标志的所有麻烦吗?
提前感谢你对这件事的任何启示,我不知道什么是最好的方法。
一个不错的选择是让List<diseases>
容纳一个人。
public class Person
{
public string Name { get; set; }
public List<diseases> Diseases { get; set; }
public Person(string name)
{
this.Name = name;
Diseases = new List<diseases>();
}
}
这样就可以相对容易地枚举所有的值,而不必担心标志。
例如:var bob = new Person("bob");
bob.Diseases.Add(diseases.gunshot);
var hasHeadache = bob.Diseases.Any(x => x == diseases.headache);
枚举是表示一种疾病的一种合理(但有点简单)的方式。
如果某人可能有N种疾病,那么只需使用该类型对象的容器,例如列表。但是您需要选择正确的容器。疾病列表可以是,例如:{ headache, throat, headache, throat, gunshot }
。列表允许重复。你真正需要的可能是一组疾病。set是一种不允许重复的结构。
选择如何表示一种疾病和一个人可能有N种疾病的事实,所以你需要一个人有一个疾病的容器,这是两个完全独立的事实。
在枚举中使用FlagsAttribute
[Flags]
Public enum diseases
{
// your values here
}
这里有很多意见被问及,正确的答案是,在任何给定的情况下,哪种解决方案是正确的取决于很多变量。您可以使用ENUM来表示多个值,只要给ENUM指定了[Flags]
属性。请记住,如果你决定走这条路,那么你负责分配ENUM特定的非重叠值的值,如1,2,4,8,16,32等
- 在这里使用enum是最好的选择吗? -这取决于你想覆盖多少疾病。如果数量很少(10…20),并且列表很平(没有疾病等级),那么你就没问题。否则,考虑其他选择。
-
[System.Flags]
是一个好方法吗? -是的,在一个小的,扁平的,列表[System.Flags]
方法是非常好的和非常有效的。 -
我应该从疾病中创建第二个属性并避免使用位标志的所有麻烦吗?使用第二个属性来代替运行集合是一个糟糕的主意。如果你必须做一件事两次,你很可能会做
N
次。创建一个集合或位字段,永远不要使用第二个属性,除非系统本身限制为两个项(例如,二叉树)。
如果疾病列表不是"平坦"(例如,您计划使用ViralThroat
, BacterialThroat
和ThroatInjury
来代替您现在拥有的简单throat
),您最好将疾病建模为类,并创建附属于Person
的疾病集合。您可以添加方法来检查特定疾病的集合,这对于搜索来说可能是明智的:例如,当传递throat
作为搜索条件时,查找任何类型的喉咙子疾病。
enum只是这里许多完全可以接受的选项之一。其他包括OO解决方案,如基类/派生类,或简单的字符串列表(或枚举的事件列表,为什么不呢?!)通常最简单的方法是最好的。
虽然使用Flags是一种解决方案,但我不建议在这种情况下使用它。标志并不冗长地说明它们的作用。每当我使用标志时,我都必须重新学习如何在需要修改代码时正确地使用标志。一种简单的替代方法是为每种可能的疾病创建属性…
public class Diseases
{
public bool Headache {get;set;}
...
public bool HasAnyDisease() { return Headache || Throat || ...;}
}
但这也有它的缺点。它不容易扩展。我建议使用装饰器模式。每种疾病都可以修饰类,这可能使将来与它的交互更容易维护。如果你需要有不同的疾病组合导致不同的结果,从长远来看,这可能会更好。