3

I am lately starting a project and I have a question.

Let's say I am dealing with a class Person, and a person can have one(or more) deseases he is encountering. so I have created an enum :

 public enum diseases{headache,throat,bruise,gunshot,none}; // enum containing all the diseases
 public diseases disease; 

And further in code I set a certain disease to that person and it works fine.

Thing is, there might be a point in my project where a person might have 2 diseases. So there are my questions:

  1. Is using enum the best option here? I want my code to be organized and understood and that's a main reason for using enums.
  2. If using enum is a good option, I have managed to combine this enum with bit-flags(using [System.Flags]) so when time comes I can check for a disease that contains two different values from the enum. is this a good approach?
  3. If using enum is a good option, should I just create a second property from diseases (just like I created disease) and save all the trouble from using bit-flags?

Thanks in advance for any light on that matter, couldn't figure what was the best approach here.

Oranges
  • 185
  • 2
  • 12
  • 7
    Use a `List` or [`[Flags]`](http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c?rq=1)? – gunr2171 Aug 25 '14 at 15:09
  • I did manage to use flags, it sounds a bit tricky to mess around with bit-flags for the rest of my project. why will a list be a good choice in here ? – Oranges Aug 25 '14 at 15:11
  • 1
    One problem with using `enum` is that it [cannot be larger than a `long`](http://msdn.microsoft.com/en-us/library/aa664597%28v=vs.71%29.aspx). So if you are using the bitmasking functionality of the enum to represent multiple diseases, your design will only handle up to 64 diseases. – dbc Aug 25 '14 at 15:28

7 Answers7

4

A good option would to make a List<diseases> to hold for a single person.

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>();
    }
}

This way you can enumerate over all the values relatively easily without having to worry about flags.

For example:

var bob = new Person("bob");
bob.Diseases.Add(diseases.gunshot);

var hasHeadache = bob.Diseases.Any(x => x == diseases.headache);
gunr2171
  • 10,315
  • 25
  • 52
  • 75
  • Thanks alot for the comment. I have never really worked around enums before so: You actually create a list that it's generic type is an enum? – Oranges Aug 25 '14 at 15:16
  • 1
    You can create a List of ANY type. Doesn't matter if it's a class, structure, enum, or interface. A List has no generic argument restrictions. – gunr2171 Aug 25 '14 at 15:16
2

An enum is a plausible (yet a bit simplistic) way to represent one disease.

If someone may have N diseases, then just use a container of objects of that type, such as a list. But you need to choose the right container. A list of diseases may be, for example: { headache, throat, headache, throat, gunshot }. Lists allow duplicates. Whay you may actually need is a set of diseases. A set is a structure which does not allow duplicates.

The choice of how you represent one disease and the fact that a person may have N diseases, so that you need a person to have a container of diseases, are two totally independent facts.

Daniel Daranas
  • 21,689
  • 9
  • 60
  • 108
  • Let's say the N will not be greater than 5 in any case, what approach will fit best? – Oranges Aug 25 '14 at 15:13
  • Could you also give an example using a container for that matter? Thanks alot ! – Oranges Aug 25 '14 at 15:14
  • @Oranges See this tutorial: [Using Sets in C#](http://cplus.about.com/od/learnc/a/csharp-sets-and-hashset.htm). – Daniel Daranas Aug 25 '14 at 15:15
  • Why would you use a HashSet instead of a List? Never heard of it before. Thanks ! – Oranges Aug 25 '14 at 15:19
  • @Oranges, HashSets are faster to lookup a single item than Lists. This is because you are comparing a hash of each element instead of the entire element. [See more](http://stackoverflow.com/q/6391738/1043380) – gunr2171 Aug 25 '14 at 15:28
  • @Oranges I wrote that in the answer. Read it again, especially this part: "Lists allow duplicates. Whay you may actually need is a set of diseases. A set is a structure which does not allow duplicates." – Daniel Daranas Aug 25 '14 at 15:43
1

Use the FlagsAttribute on your enum.

[Flags]
Public enum diseases 
{
    // your values here
}

This should give you what you need.

ZombieSheep
  • 28,629
  • 10
  • 64
  • 112
1

There is a lot of opinion being asked for here and the right answer is that it depends on a lot of variables what solution is right in any given situation. You CAN use an ENUM to represent multiple values so long as the [Flags] attribute is given to the ENUM. Keep in mind that if you decide to go that route then you are responsible for assigning the values of the ENUM specific non-overlapping values like 1, 2, 4, 8, 16, 32, etc.

Rob Epstein
  • 1,122
  • 6
  • 10
1
  1. Is using enum the best option here? - This depends on how many diseases you would like to cover. If the number is small (10..20) and the list is flat (no hierarchy of diseases) then you are fine. Otherwise, consider some alternative.
  2. is [System.Flags] a good approach? - Yes, in case of a small, flat, list [System.Flags] approach is very good and extremely efficient.
  3. Should I just create a second property from diseases and save all the trouble from using bit-flags? Having a second property in place of running a collection is a terrible idea. If you have to do something twice, chances are, you'd do it N times. Make a collection or bit fields, never go for a second property unless the system is inherently limited to two items (say, a binary tree).

If the list of diseases is not "flat" (e.g. you plan to have ViralThroat, BacterialThroat, and ThroatInjury in place of a simple throat that you have now) you would be better off modeling diseases as classes, and creating a collection of diseases attached to a Person. You could add methods for checking the collection for particular diseases, which could be smart about the search: for example, find any kind of throat sub-disease when a throat is passed as a search criterion.

Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
0

enum is just one of many perfectly acceptable options here. Others include OO solutions such as base/derived classes, or simple lists of string (or event lists of enums, why not?!). Often the simplest approach is best. We would have to know a lot more about your problem to recommend one over the other.

Michael Gunter
  • 11,826
  • 1
  • 20
  • 52
0

While using Flags is one solution, I would not recommend it in this case. Flags are not verbose on what they are for. Any time I used flags, I would have to re-learn how to properly work with flags when I needed to modify my code. One simple alternative is creating a property for each possible disease...

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

But that has it's downsides as well. It's not easily extensible. I would recommend using the Decorator Pattern. Each disease could decorate the class which may make future interactions with it easier to maintain. If you need to have variance disease combinations cause different outcomes, this may be better in the long run.

Onosa
  • 1,227
  • 1
  • 13
  • 24