tags:

views:

203

answers:

2

I have an enum that enumerates integer values returned from an external API for easier use in my code. But I don't necessarily know the integer values at compile time, so I have some code that hooks them up at program start and stores them in a Dictionary.

I've defined some extension methods for conversion to/from the integer codes, but these integer codes aren't the same as what would be returned from a cast to int. If another programmer were to program with my enum I'm afraid they'd try casting to and from integers out of force of habit. And the program would just silently accept the bad code.

Is there a way to prevent explicit conversion of my enum to/from int? If not, is there a way to cause an exception to be thrown if someone tries? Or hook up my own conversion functions? Or change the underlying value of an enum at run time?

+8  A: 

What you are trying is very "dirty".

Use a static class with readonly values instead of the enums. You can then initialize the values in the type initializer (or via a static method):

public static class Foos
{
    public static readonly int First;
    public static readonly int Second;

    //...

    static Foos()
    {
        //For Example:
        First = DateTime.Now.Day;
        First = DateTime.Now.Month;
    }
}
winSharp93
Very, very dirty indeed.
GalacticCowboy
I wanted to avoid using a class like that, but I might just opt for it anyway, based on the difficulties I've been experiencing.
Jay Lemmon
+1  A: 

Another way of doing this that might make sense: define the Enum in your program and map the external API's values to the Enum in private methods. In other words, don't expose the external API's type anywhere inside your object model. For example:

public enum MyEnum { First, Second, Third };

public class MyApiWrapper
{
   private Dictionary<int, int> ExternalToInternal = new Dictionary<int, int>();
   private Dictionary<int, int> InternalToExternal = new Dictionary<int, int>();

   public MyApiWrapper(List<int> externalApiEnumValues)
   {
      foreach (int i = 0; i < externalApiEnumValues.Count; i++)
      {
         ExternalToInternal[externalApiEnumValues[i]] = i;
         InternalToExternal[i] = externalApiEnumValues[i];
      }
   }

   // obviously, your real method for calling the external API 
   // will do more than this.
   public void CallApi()
   {
      CallExternalApi(_EnumValue);
   }

   private MyEnum _ExternalEnumValue;
   public MyEnum EnumValue
   {
      get { return ExternalToInternal[_ExternalEnumValue]; }
      set { _ExternalEnumValue = InternalToExternal[value]; }
   }
}

As long as all access to the API is done through this class (one hopes you've already encapsulated external-API access in a class), you can freely use MyEnum everywhere inside your application without being concerned about what other programmers do with the values.

Robert Rossney
Unfortunately it's a large legacy code base so there isn't a single choke point like that. There are calls _everywhere_. I'm trying to bite off manageable chunks and refactor them, but I keep running in to situations like this where I can't fix everything at once and I can't guarantee that other coders won't continue bad habits.
Jay Lemmon