Typesafe Enum Pattern

  • Thread starter Thread starter Steven Nagy
  • Start date Start date
S

Steven Nagy

So I was needing some extra power from my enums and implemented the
typesafe enum pattern.
And it got me to thinking... why should I EVER use standard enums?

There's now a nice little code snippet that I wrote today that gives me
an instant implementation of the pattern. I could easily just always
use such an implementation instead of a standard enum, so I wanted to
know what you experts all thought.

Is there a case for standard enums?

I also noticed its very hard to find good examples of what can be
achieved with the pattern in a .NET context. Do a google for (
"typesafe enum pattern" -java ) and you don't get very many results!

Opinions?
 
C# enumerations *are* type-safe. There is no such thing as a non-type-safe
enumeration. In C#, enumerations are inherited from the value type
System.Enum, which is a structure. There can be no confusion of enumeration
members and their integral counterparts without an explicit cast.

As for your difficulty in Googling the subject, try leaving off the word
"pattern" (i.e. "typesafe enum"). Of course, all references you find will be
related to the Java programming language because, as I said, C# enumerations
*are* type-safe.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

A watched clock never boils.
 
Thanks Kevin.

Yes I know enums are type-safe. I was more interested in the actual
pattern.
Its not the aspect of being type-safe that my question relates to, and
I suppose in that context my question could have been misleading.

The pattern is based around providing a class instead of an enum and
thus realising more potential as a class than an enum could. My
interest is around that, and what people have found to be useful about
the pattern, or perhaps what people have discovered that a standard
enum provides that an implementation of the pattern could not.

Thanks,
Steven
 
Hi Steven,

Actually, the Java type-safe enum is similar to .Net enums. It is the older
Java implementation that is exposed only as a class, and is not type-safe.

But it is entirely possible to create a class like that in .Net.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

A watched clock never boils.
 
Hi again Kevin,
Actually, the Java type-safe enum is similar to .Net enums. It is the older
Java implementation that is exposed only as a class, and is not type-safe.
But it is entirely possible to create a class like that in .Net.

Yes and this brings me to the "requested input" from professionals like
yourself.
Do you value the pattern in a C# setting? When do you find yourself
implementing this pattern? What advantages do you see the standard
enums having over an implementation of this pattern in C#?

I'm not interested in syntax, I'm interested in pros and cons.

Cheers,
Steven
 
Also, could you expand on this a bit more...
and is not type-safe.

Is the type-safe enum pattern not type-safe?
Why is this so? The implementations in Java that I have seen seem to be
type safe.
I guess if I am creating a class called Foo and have this code:

Foo SomeFoo = Foo.Bar;
if (SomeFoo == Foo.Bar) { ... }

Is this not typesafe?

Cheers,
Steven
 
Here's a simplified explanation:
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

As for whether I think it's a good idea to use the non-type-safe pattern, no
I don't think so, for the reasons explained in the Sun Java reference above.
The .Net enum is the best of all worlds, type-safe, and concise. Very
similar to the original C enum syntax.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

A watched clock never boils.
 
Hi Kevin,

I think we are talking about 2 different things. That link refers to
the "int enum pattern" which is definately not type-safe. However I am
referring to the "type-safe enum pattern" which to my understanding IS
type save and is covered only briefly in that article, saying that its
fault is that it can't be used in a switch statement (in the Java
language). So I guess this brings me to the following lines of thought:

1. I need to check out tonight if coding the equivalence operator in C#
is enough for switch statements. (ie. public static bool operator
==(object a, object b) { ... } )
If this works, or there is at least a specific operator for switch
statements, then the only identified fault with the typesafe enum
pattern in java does not apply to .NET.

2. From what I can tell, Java allows you to write static methods inline
with your enum, creating that encapsulation. I am not sure if C# lets
you do this as well. Something else to investigate when I get home
tonight.
As for whether I think it's a good idea to use the non-type-safe pattern, no

I was referring to the type safe pattern, not the non-type-safe
pattern.
I don't think so, for the reasons explained in the Sun Java reference above.
The .Net enum is the best of all worlds, type-safe, and concise. Very

Concise is good at times. And sure, for small stuff, the standard enum
is fine. But there comes a time when you need to push the boundaries a
bit, thus back to my original question about pros and cons of both.

Hopefully this has cleared up my position and what I am trying to learn
here.

Cheers,
Steven
 
Hi Steven,

Here's my take on why I think one should use an Enum instead of a class with a list of constant values:

1. Enum instances act like the underlying Type, which must be a struct, not a class. You won't be able to provide even some of the
same functionality in a class without using operator overloads and even then you won't get editor or compiler support for the
underlying Type. Every time you pass an instance of your class it will be an object reference. Enum values are structs and
therefore instances of an Enum are always passed as a value unless the ref or out parameter modifier is used. (This is true even
though the Enum Type derives from object. You can test this by using the static Object.ReferenceEquals method.)
2. Enums support implicit conversion from and explicit conversion to the underlying Type. (This can be accomplished in a class by
overloading the implicit and explicit casting operators, however)
3. Enums have built-in support for conversion to and from string representations of the underlying Type or the name of the
constants.
4. Enums have built-in support for the FlagsAttribute attribute.
5. Designers have built-in support to handle Enums in a way that is useful to developers.
6. Enums encapsulate a single idea: a list of related constant values with only one "chosen" value at any time. By passing an
instance of an Enum to a method your are essentially passing in one of the constants that it contains. If you need a single value
to be chosen from a list of constants and passed into a related method, for example, I think it's perfectly reasonable to code a
class for the method and an Enum for the constants. If you can think of an example where it would be reasonable to combine a class
and an Enum into a single Type I'd love to here it because I couldn't think of one.

HTH
 
Kevin Spencer said:
Here's a simplified explanation:
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

As for whether I think it's a good idea to use the non-type-safe pattern, no
I don't think so, for the reasons explained in the Sun Java reference above.
The .Net enum is the best of all worlds, type-safe, and concise. Very
similar to the original C enum syntax.

The .NET enum is a very long way from the best of all worlds.

1) It's completely non-OO. Just because there's a fixed set of values,
why should that mean the type can't have any other data (attributes
aren't really adequate or elegate) or behaviour
2) It's not type-safe when it's boxed
3) It allows (and can't disallow) values which aren't in the defined
set

The Java enum is fantastically useful, and I'd love to see an
equivalent - or even better - mechanism in C# and .NET. See
http://msmvps.com/blogs/jon.skeet/archive/2006/01/05/classenum.aspx
for more on my thoughts about it.
 
Dave Sexton said:
Here's my take on why I think one should use an Enum instead of a
class with a list of constant values:

1. Enum instances act like the underlying Type, which must be a
struct, not a class. You won't be able to provide even some of the
same functionality in a class without using operator overloads and
even then you won't get editor or compiler support for the underlying
Type. Every time you pass an instance of your class it will be an
object reference. Enum values are structs and therefore instances of
an Enum are always passed as a value unless the ref or out parameter
modifier is used. (This is true even though the Enum Type derives
from object. You can test this by using the static
Object.ReferenceEquals method.)

I don't see why passing a reference by value is any worse than passing
an int by value.
2. Enums support implicit conversion from and explicit conversion to
the underlying Type. (This can be accomplished in a class by
overloading the implicit and explicit casting operators, however)

Only explicit conversion, aside from the constant of 0. Why is this an
advantage though? If you want to attach an integral value to the class-
based enum, you can easily do so.
3. Enums have built-in support for conversion to and from string
representations of the underlying Type or the name of the constants.

Easy to achieve manually, and could be easily automatic with more
compiler and CLR support. (It's available in Java 5 enums.)
4. Enums have built-in support for the FlagsAttribute attribute.

Java has EnumSet, which you easily build an equivalent of.
5. Designers have built-in support to handle Enums in a way that is
useful to developers.

Again, that's only because .NET doesn't have enhanced enums yet.
6. Enums encapsulate a single idea: a list of related constant values
with only one "chosen" value at any time. By passing an instance of
an Enum to a method your are essentially passing in one of the
constants that it contains. If you need a single value to be chosen
from a list of constants and passed into a related method, for
example, I think it's perfectly reasonable to code a class for the
method and an Enum for the constants. If you can think of an example
where it would be reasonable to combine a class and an Enum into a
single Type I'd love to here it because I couldn't think of one.

Enums provide a link between a name and a value within a namespace (the
enum type). That's all - and that sucks. Do you insist that all your
other types only have one or two pieces of data and very limited
behaviour? Why should the related values not have extra data?

I suspect you can't see the uses for more advanced functionality
because you haven't *had* that advanced functionality. I've found that
it takes Java programmers quite a while to embrace enhanced enums, but
that when they do there are several "natural fits" which make the
coding *much* nicer.
 
Hi Jon,
I don't see why passing a reference by value is any worse than passing
an int by value.

I'm not sure what you mean by that. I was just trying to explain that an instance of an Enum acutally behaves like a value-type
(Curiously though, VS.NET shows "class" on the tooltip for "Enum" in code, although it derives from ValueType). If you want to
produce the same functionality as Enums (or as close as you can get, but with custom state and behavior) using the tools that are
currently at your disposal, then you'd be better off using a struct, not a class.

I think this directly addresses the point of the OP. The author claims to have written a class using the current framework, at
least so it seems, to extend the Enum type. I intended my reply to address some of the concerns I would have if someone gave me
this new class and I had to use it in place of Enums.
Only explicit conversion, aside from the constant of 0. Why is this an
advantage though? If you want to attach an integral value to the class-
based enum, you can easily do so.

My mistake on the implicit part.

It's an advantage because Enum already exists as a primitive in the framework, supplying that functionality. The point is that you
can code it in a class by using casting overloads however it's just more work trying to reinvent the wheel, IMO.
Easy to achieve manually, and could be easily automatic with more
compiler and CLR support. (It's available in Java 5 enums.)

Of course it's easy, but it's just more work trying to reinvent the wheel before you can extend its behavior.

I was listing all of the aspects of Enum that one would have to reproduce if they wanted to extend its behavior using a class in the
current framework. The point being that Enum is a primitive Type that already provides all of this functionality. My last point
addresses why I think this is important.

Maybe I can make my POV clearer by asking you if you have a class that you wrote in .NET that extends enums and that you use in
place of them? If not, that's my point exactly. If so, then I give up. I'm easy ;)
Java has EnumSet, which you easily build an equivalent of.

I'm not arguing that a more robust Enum type, as a primitive, wouldn't be a welcomed addition. Again I'm just trying to address the
OP. Enums have that support now and I would expect the author's class to have it as well before I used it in place of Enums.
Again, that's only because .NET doesn't have enhanced enums yet.

Yet. But I don't think that addresses the OP ;) The author wrote a custom class using the current framework. If the author
wishes to extend their class for designer support they could do so, of course, but personally I'd rather just use a simple Enum
right now.
Enums provide a link between a name and a value within a namespace (the
enum type). That's all - and that sucks. Do you insist that all your
other types only have one or two pieces of data and very limited
behaviour? Why should the related values not have extra data?

Ok, I don't insist that all of my other types have only one or two pieces of data and very limited behavior, however I do insist
that they aren't framework primitives that address a particular, compile-time need ;)
I suspect you can't see the uses for more advanced functionality
because you haven't *had* that advanced functionality. I've found that
it takes Java programmers quite a while to embrace enhanced enums, but
that when they do there are several "natural fits" which make the
coding *much* nicer.

Well, I never said that! My post wasn't against the idea of a primitive Type that addresses your concerns, but instead it was
against the idea of creating an Enum-enhanced type using a class in the current framework. After reading your article I can see how
I might benefit from it, however I do agree that if I had it and used it, I could probably appreciate the idea more than I do now.

As for the lack of Type-safety in Enums I don't think it's any reason to be concerned. They are value-types, so it's the value that
is important, not the Type.
 
I'm not sure what you mean by that. I was just trying to explain that an instance of an Enum acutally behaves like a value-type
(Curiously though, VS.NET shows "class" on the tooltip for "Enum" in code, although it derives from ValueType). If you want to
produce the same functionality as Enums (or as close as you can get, but with custom state and behavior) using the tools that are
currently at your disposal, then you'd be better off using a struct, not a class.

I think this directly addresses the point of the OP. The author claims to have written a class using the current framework, at
least so it seems, to extend the Enum type. I intended my reply to address some of the concerns I would have if someone gave me
this new class and I had to use it in place of Enums.

Well its no claim, its fact... but I'm just adhering to the concepts of
the pattern. Its very well documented.
Here's a brief sample from my chess application (note that there's
nothing really in here that you can't do currently with enums and
attributes):

public class GameStatus
{
private int _value = 0;
public int Value
{
get
{
return _value;
}
}
private string _title = "";
public string Title
{
get
{
return _title;
}
}

public static readonly GameStatus WhiteWins = new GameStatus(3,
"White Wins");
public static readonly GameStatus BlackWins = new GameStatus(4,
"Black Wins");
public static readonly GameStatus Stalemate = new GameStatus(5,
"Stalemate");

private GameStatus(int value, string title)
{
_value = value;
_title = title;
}

public override string ToString()
{
return _title.Replace(" ", "");
}

public static bool operator ==(GameStatus gs1, GameStatus gs2)
{
return (gs1.Value == gs2.Value);
}
public static bool operator !=(GameStatus gs1, GameStatus gs2)
{
return (gs1.Value != gs2.Value);
}
}
I'm not arguing that a more robust Enum type, as a primitive, wouldn't be a welcomed addition. Again I'm just trying to address the
OP. Enums have that support now and I would expect the author's class to have it as well before I used it in place of Enums.

Its not a general replacement for enums.. its a specific scenario as
per the example above.
Its not like I am writing " public class ABetterEnum : Enum { ... } "
Yet. But I don't think that addresses the OP ;) The author wrote a custom class using the current framework. If the author
wishes to extend their class for designer support they could do so, of course, but personally I'd rather just use a simple Enum
right now.

I think this is off topic. I think at this point we all concede that we
can replicate an enum with a class.

What if that single idea is bigger than what the enum can support?

I think this is one of the key pros for the pattern that I was looking
for. With enums, its the value (usually numeric) and the actual enum
constant name. With a class implementation its 2 to infinity (and
beyond!). So in my code example above, I actually have 3: the int
value, the string title (which in this case is a friendly name that can
show in screen) and a usable name (shown in the ToString() method).
Ok, I don't insist that all of my other types have only one or two pieces of data and very limited behavior, however I do insist
that they aren't framework primitives that address a particular, compile-time need ;)

Oh but they do address a compile-time need.
I can write code like this:
GameStatus CurrentStatus = GameStatus.WhiteWins;
Label1.Text = CurrentStatus.Title;

I admit that I had heard of the pattern only recently and it is
incredibly rare in .NET circles (as far as I can tell) but not useless.
As for the lack of Type-safety in Enums I don't think it's any reason to be concerned. They are value-types, so it's the value that
is important, not the Type.

I'm sorry but I disagree. The Type is extremely important. I'd rather
see errors at compile time than at run-time.

I really appreciate both your inputs in this, so please, both keep
posting!

Steven
 
On a similar vain, you could also do something here by marking the
individual enum values with attributes to hold the full name, and a helper
class to obtain these as required (see below); only nuicance here is that
the helper class must use reflection (.GetCustomAttributes) on the enum
values (held as fields on the Type). And globalization would still need some
kind of lookup code in the But in its favor:

* The same helper class can be used with any enum
* It is faithful to the CLR enum model
* Like the OP, supports (in theory) multiple characteristics by extending
the attribute or adding additional attributes

I'm not saying it's the worlds best implementation ever... but it works ;-p

Marc

(add [EnumMarkup("Some Description")] before an enum item definition)

[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]
public class EnumMarkupAttribute : Attribute {
public readonly string Description;
public EnumMarkupAttribute(string description) {
if (description == null) throw new
ArgumentNullException("description");
Description = description;
}
}
public static class EnumHelper<T> where T : struct {
private static Dictionary<T, string> _valueToDescription;
private static Dictionary<string, T> _descriptionToValue;
static EnumHelper() {
Type enumType = typeof(T), attributeType =
typeof(EnumMarkupAttribute);
_descriptionToValue = new Dictionary<string, T>();
_valueToDescription = new Dictionary<T, string>();
foreach (string name in Enum.GetNames(enumType)) {
T value = (T) Enum.Parse(enumType, name);
string desc = name;
foreach (EnumMarkupAttribute attrib in
enumType.GetField(value.ToString()).GetCustomAttributes(attributeType,
false)) {
desc = attrib.Description;
break; // only expect one per enum value anyway!
}
_valueToDescription[value] = desc;
_descriptionToValue[desc] = value;
}
}
public static T ParseDescription(string description) {
T value;
if (!_descriptionToValue.TryGetValue(description, out value)) {
throw new ArgumentException(string.Format("Enum \"{0}\" not
found by description \"{1}\"",typeof(T).Name, description ?? "<null>"),
"description");
}
return value;
}
public static string GetDescription(T value) {
string description;
if (!_valueToDescription.TryGetValue(value, out description)) {
description = value.ToString();
}
return description;
}
public static string GetName(T value) {
return Enum.GetName(typeof(T), value);
}
public static T ParseName(string value) {
return (T)Enum.Parse(typeof(T), value);
}
public static T ParseName(string value, bool ignoreCase) {
return (T)Enum.Parse(typeof(T), value, ignoreCase);
}
public static T[] GetValues() {
Array array = Enum.GetValues(typeof(T));
T[] result = new T[array.Length];
array.CopyTo(result, 0);
return result;
}
public static string[] GetNames() {
return Enum.GetNames(typeof(T));
}
public static string[] GetDescriptions() {
T[] values = GetValues();
int length = values.Length;
string[] result = new string[length];
for (int i = 0; i < length; i++) {
result = GetDescription(values);
}
return result;
}
}
 
Hi Steven,
Well its no claim, its fact... but I'm just adhering to the concepts of
the pattern. Its very well documented.

At least I can be sure of that. Thanks for posting the code snippet too.
Here's a brief sample from my chess application (note that there's
nothing really in here that you can't do currently with enums and
attributes):
<snip>

Your class should probably be a struct, and in that case you should override Equals and GetHashCode as well. Also, you might want
to implement IComparable said:
Its not a general replacement for enums.. its a specific scenario as
per the example above.
Its not like I am writing " public class ABetterEnum : Enum { ... } "

Well, you did write code so that your class would exhibit the behavior of Enum before you could "extend" it, otherwise it wouldn't
have replaced Enum. Essentially, you have combined a class with an enum. In the current framework, that's really your only choice
to meet your specific needs.
I think this is off topic. I think at this point we all concede that we
can replicate an enum with a class.

If you have the time and desire, yes ;)
What if that single idea is bigger than what the enum can support?

Then you should use a different architecture. I never said that you have to use enums.
I think this is one of the key pros for the pattern that I was looking
for. With enums, its the value (usually numeric) and the actual enum
constant name. With a class implementation its 2 to infinity (and
beyond!). So in my code example above, I actually have 3: the int
value, the string title (which in this case is a friendly name that can
show in screen) and a usable name (shown in the ToString() method).

Well then you can't use an Enum if you need more functionality then it provides. It's just that simple. In the current framework,
if you implement it as a class then you really can't call it an Enum. It's a custom Type.

You asked in your OP to provide an argument for the use of Enums. I think I did just that. They provide some specific needs and
they do it well. Now, it seems, that you wanted arguments against the proposition of extensions to enums in a later framework
version, but I'm not against that. ;)
Oh but they do address a compile-time need.
I can write code like this:
GameStatus CurrentStatus = GameStatus.WhiteWins;
Label1.Text = CurrentStatus.Title;

I think Jon was suggesting that Enum, as a primitive, is too restrictive but he tried to illustrate that point by suggesting that it
wouldn't make sense if my classes had to sacrifice data too. I'm not suggesting that your implementation doesn't address some
specific compile-time need, I'm simply suggesting that Enums do and that custom Types that don't provide the same functionality as
Enums can't be compared to them. If I need more than an Enum offers, I can always create a class, for now :)

I'm sorry but I disagree. The Type is extremely important. I'd rather
see errors at compile time than at run-time.

Well, that's impossible if you are using FlagsAttribute and relying on external input that isn't type safe. Here it's the value
that is important, not the Type. I believe that is the case with most, if not all, value-types. Semantically, I think that's the
point.

I do, of course, appreciate Type safety but it's just not always possible, or reasonable for that matter.
I really appreciate both your inputs in this, so please, both keep
posting!

NP.
 
Hi Jon,

I do appreciate the language enhancements that continue to evolve in C#, but
to me an enum is an enum (as in the original C spec), and a class is a
class. I would have no problem with MS adding such a class, but I have no
desire to see it done either. If I need one, I can always write one.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

A watched clock never boils.
 
Marc Gravell said:
On a similar vain, you could also do something here by marking the
individual enum values with attributes to hold the full name, and a helper
class to obtain these as required (see below); only nuicance here is that
the helper class must use reflection (.GetCustomAttributes) on the enum
values (held as fields on the Type). And globalization would still need some
kind of lookup code in the But in its favor:

* The same helper class can be used with any enum
* It is faithful to the CLR enum model
* Like the OP, supports (in theory) multiple characteristics by extending
the attribute or adding additional attributes

Downsides:

1) It only works with values which are available as attributes (okay in
this particular case, but not in general)

2) It's ugly

3) It leaves the same issue of invalid enum values (i.e. any integral
value of the appropriate type can be cast to the enum type)
 
Kevin Spencer said:
I do appreciate the language enhancements that continue to evolve in C#, but
to me an enum is an enum (as in the original C spec), and a class is a
class. I would have no problem with MS adding such a class, but I have no
desire to see it done either. If I need one, I can always write one.

An "enum" is just an enumeration of values as far as I'm concerned. You
can't apply attributes to C enums - so does that mean we shouldn't be
able to apply them in C#? Why is enum different to struct? There are
lots of things you can do with C# structs which you can't do with C
structs - they've become object-oriented. Why not perform the same sort
of change to enums?

And while you *can* write one, there are disadvantages to doing so
compared with having a version in the language/framework:

1) Different people will have different implementations
2) You can't use it (elegantly) in a switch statement
3) There's extra code to be written which could easily be provided by
the framework
 
Well, yes, this is object-oriented, but for some reason I just can't see
redefining a type so radically. It seems like redefining integer, or byte as
an object. IMHO, it would be better to add a new type.

--

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

A watched clock never boils.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top