It recently occured to me that the following (sample) enumeration...
enum Color
{
Red,
Green,
Yellow,
Blue
}
... could be replaced with a seemingly more type-safe class:
class Color
{
private Color() { }
public static readonly Color Red = new Color();
public static readonly Color Green = new Color();
public static readonly Color Yellow = new Color();
public static readonly Color Blue = new Color();
}
With "type-safe", I mean that the following statement would work if Color
was an enum, but not if Color
were the above class:
var nonsenseColor = (Color)17; // works if Color is an enum
1) Is there a widely accepted name to this pattern (replacing an enum with a type-safe class)?
2) In which cases should one use enums, and when would a class be more appropriate?
Enums are great for lightweight state information. For example, your color enum (excluding blue) would be good for querying the state of a traffic light. The true color along with the whole concept of color and all its baggage (alpha, color space, etc) don't matter, just which state is the light in. Also, changing your enum a little to represent the state of the traffic light:
[Flags()]
public enum LightColors
{
unknown = 0,
red = 1,
yellow = 2,
green = 4,
green_arrow = 8
}
The current light state could be set as:
LightColors c = LightColors.red | LightColors.green_arrow;
And queried as:
if ((c & LightColors.red) == LightColors.red)
{
//Don't drive
}
else if ((c & LightColors.green_arrow) == LightColors.green_arrow)
{
//Turn
}
Static class color members would be able to support this multiple state without extra functionality.
However, static class members are wonderful for commonly used objects. The System.Drawing.Color
members are great examples as they represent a known-name colors that have obscure constructors (unless you know your hex colors). If they were implemented as enums you would have to do something like this every time you wanted to use the value as a color:
colors c = colors.red;
switch (c)
{
case colors.red:
return System.Drawing.Color.FromArgb(255, 0, 0);
break;
case colors.green:
return System.Drawing.Color.FromArgb(0,255,0);
break;
}
So if you've got an enum and find that your constantly doing a switch/case/if/else/whatever to derive an object, you might want to use static class members. If you're only querying the state of something, I'd stick with enums. Also, if you have to pass data around in an unsafe fashion enums will probably survive better than a serialized version of your object.
Edit: @stakx, I think you stumbled on something important, too in response to @Anton's post and that is complexity or more importantly, who is it complex for?
From a consumer's standpoint, I would immensely prefer System.Drawing.Color static class members over having to write all of that. From a producer's standpoint, however, it would be a pain to have to write all of that. So if other people are going to be using your code you might be saving them a lot of trouble by using static class members even though it might take you 10 times as long to write/test/debug. However, if its just you you might find it easier to just use enums and cast/convert as needed.