23

My question is best illustrated with an example.

Suppose I have the enum:

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

I want to associate the unit vector corresponding to each direction with that direction. For example I want something that will return (0, 1) for North, (-1, 0) for West, etc. I know in Java you could declare a method inside the enum which could provide that functionality.

My current solution is to have a static method -- inside the class that defines the enum -- that returns a vector corresponding to the passed in ArrowDirection (the method uses a HashTable to accomplish the lookup but that's not really important). This seems... unclean.

Question:
Is there a best-practice solution for storing additional information corresponding to an enum in .NET?

colithium
  • 10,269
  • 5
  • 42
  • 57

5 Answers5

41

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.

ziesemer
  • 27,712
  • 8
  • 86
  • 94
Charlie Flowers
  • 17,338
  • 10
  • 71
  • 88
  • That's pretty cool. Although I knew about extensions I never thought using them for enum extension – Sergej Andrejev Mar 25 '09 at 07:17
  • Yeah, me either at first. A friend told me about it. It is very nice. I was also surprised to learn (recently, here on SO) that you can call an extension method on a null value. It still works because it is a static method. As usual, the C# team has done a great job thinking these features through. – Charlie Flowers Mar 25 '09 at 07:21
  • You're going to get the accepted answer. I tried it and it works perfectly. The only thing is. Where exactly should I declare the enum? If I leave it in the class, it says it's less accessible. I had to make a "ClassName_Enums" Class to make it work... – colithium Mar 25 '09 at 07:31
  • It turns out it makes sense to define the enum at the namespace level. Accepted. – colithium Mar 25 '09 at 07:35
  • Yes, I agree that I would go with the namespace level in most cases. – Charlie Flowers Mar 25 '09 at 07:45
  • Huh. That's awfully convenient, and I never realized you could build extension methods on enums like that. Cool! – mqp Apr 02 '09 at 21:38
3

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

Cherian
  • 19,107
  • 12
  • 55
  • 69
1
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;

    }
}
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • That doesn't look like an extension method. Where is the `this` parameter? Also, where is `ToDescription` coming from? Is that supposed to be the extension method? – CoderDennis Jun 26 '12 at 16:28
0

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).

Andy White
  • 86,444
  • 48
  • 176
  • 211
  • I've used it too and like it. But only recently I've found something I like even more. You can put extension methods onto enums! Funny how much enjoyment that brings me ... but it is really nice. – Charlie Flowers Mar 25 '09 at 07:15
0

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.

Ash
  • 60,973
  • 31
  • 151
  • 169