My question is best illustrated with an example.
Suppose I have the enum:
public enum ArrowDirection
{
North,
South,
East,
West
}
One thing you could look at is the "Type-Safe Enum" pattern. This allows you to create an enum that is actually a full-fledged static object, which can have methods/properties/etc..
http://www.javacamp.org/designPattern/enum.html
Joshua Bloch talks about this pattern in his book "Effective Java." I've used it in a lot of different situations, and I actually prefer it over plain enums. (It's language-agnostic - it works in Java, C#, or pretty much any OO language).
Your static method approach seems quite clean to me. You encapsulate both the enum and the static method within the same class. Changes to the enum are centralised within that single class.
Adding a method to the enumeration (as per Java) seems to add complexity to something that is really a very simple concept.
The attribute based approach is interesting, but once again seems to overcomplicate things when compared to a static method.
I've blogged about it here.
Try out something like this with Attributes.
public enum Status {
[Status(Description = "Not Available")]
Not_Available = 1,
[Status(Description = "Available For Game")]
Available_For_Game = 2,
[Status(Description = "Available For Discussion")]
Available_For_Discussion = 3,
}
public class StatusEnumInfo {
private static StatusAttribute[] edesc;
public static String GetDescription(object e)
{
System.Reflection.FieldInfo f = e.GetType().GetField(e.ToString());
StatusEnumInfo.edesc = f.GetCustomAttributes(typeof(StatusAttribute), false) as StatusAttribute[];
if (StatusEnumInfo.edesc != null && StatusEnumInfo.edesc.Length == 1)
return StatusEnumInfo.edesc[0].Description;
else
return String.Empty;
}
public static object GetEnumFromDesc(Type t, string desc)
{
Array x = Enum.GetValues(t);
foreach (object o in x) {
if (GetDescription(o).Equals(desc)) {
return o;
}
} return String.Empty;
}
}
public class StatusAttribute : Attribute {
public String Description { get; set; }
}
public class Implemenation {
public void Run()
{
Status statusEnum = (Status)StatusEnumInfo.GetEnumFromDesc(typeof(Status), "Not Available");
String statusString = StatusEnumInfo.GetDescription(Status.Available_For_Discussion);
}
}
Instead of Description, use your custom Property
There's a FANTASTIC new way to do this in C# 3.0. The key is this beautiful fact: Enums can have extension methods! So, here's what you can do:
public enum ArrowDirection
{
North,
South,
East,
West
}
public static class ArrowDirectionExtensions
{
public static UnitVector UnitVector(this ArrowDirection self)
{
// Replace this with a dictionary or whatever you want ... you get the idea
switch(self)
{
case ArrowDirection.North:
return new UnitVector(0, 1);
case ArrowDirection.South:
return new UnitVector(0, -1);
case ArrowDirection.East:
return new UnitVector(1, 0);
case ArrowDirection.West:
return new UnitVector(-1, 0);
default:
return null;
}
}
}
Now, you can do this:
var unitVector = ArrowDirection.North.UnitVector();
Sweet! I only found this out about a month ago, but it is a very nice consequence of the new C# 3.0 features.
Here's another example on my blog.
using System.ComponentModel;
using System.Reflection;
public enum ArrowDirection
{
[Description("Northwards")]
North,
[Description("Southwards")]
South,
[Description("Eastwards")]
East,
[Description("Westwards")]
West
}
...
Create an extension method to get a list of descriptions:
public static class Enum<T> where T : struct
{
/// <summary>
/// Gets a collection of the enum value descriptions.
/// </summary>
/// <returns></returns>
public static IList<string> GetDescriptions()
{
List<string> descriptions = new List<string>();
foreach (object enumValue in Enum<T>.GetValues())
{
descriptions.Add(((Enum)enumValue).ToDescription());
}
return descriptions;
}
}