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给那个人,它工作得很好。

问题是,在我的项目中可能有一个点,一个人可能有两种疾病。这就是我的问题:

  1. 在这里使用enum是最好的选择吗?我希望我的代码是有组织的和容易理解的,这是使用枚举的主要原因。
  2. 如果使用枚举是一个很好的选择,我已经设法将此枚举与位标志(使用[System.Flags])结合起来,所以当时间到来时,我可以检查包含两个不同值的disease从枚举。这是一个好方法吗?
  3. 如果使用enum是一个很好的选择,我应该从diseases(就像我创建disease)创建第二个属性,并避免使用位标志的所有麻烦吗?

提前感谢你对这件事的任何启示,我不知道什么是最好的方法。

Multiple choice enum

一个不错的选择是让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等

  1. 在这里使用enum是最好的选择吗? -这取决于你想覆盖多少疾病。如果数量很少(10…20),并且列表很平(没有疾病等级),那么你就没问题。否则,考虑其他选择。
  2. [System.Flags]是一个好方法吗? -是的,在一个小的,扁平的,列表[System.Flags]方法是非常好的和非常有效的。
  3. 我应该从疾病中创建第二个属性并避免使用位标志的所有麻烦吗?使用第二个属性来代替运行集合是一个糟糕的主意。如果你必须做一件事两次,你很可能会做N次。创建一个集合或位字段,永远不要使用第二个属性,除非系统本身限制为两个项(例如,二叉树)。

如果疾病列表不是"平坦"(例如,您计划使用ViralThroat, BacterialThroatThroatInjury来代替您现在拥有的简单throat),您最好将疾病建模为类,并创建附属于Person的疾病集合。您可以添加方法来检查特定疾病的集合,这对于搜索来说可能是明智的:例如,当传递throat作为搜索条件时,查找任何类型的喉咙子疾病。

enum只是这里许多完全可以接受的选项之一。其他包括OO解决方案,如基类/派生类,或简单的字符串列表(或枚举的事件列表,为什么不呢?!)通常最简单的方法是最好的。

我们必须对你的问题了解得更多才能给你推荐一个。

虽然使用Flags是一种解决方案,但我不建议在这种情况下使用它。标志并不冗长地说明它们的作用。每当我使用标志时,我都必须重新学习如何在需要修改代码时正确地使用标志。一种简单的替代方法是为每种可能的疾病创建属性…

public class Diseases
{
public bool Headache {get;set;}
...
public bool HasAnyDisease() { return Headache || Throat || ...;}
}

但这也有它的缺点。它不容易扩展。我建议使用装饰器模式。每种疾病都可以修饰类,这可能使将来与它的交互更容易维护。如果你需要有不同的疾病组合导致不同的结果,从长远来看,这可能会更好。