tags:

views:

191

answers:

5

Given an enum that has assigned values, what is the best way to get the next or previous enum given a value. For example, consider this enum:

public enum TimeframeType {
    None = 0,
    [Description("1 month")]
    Now = 30,
    [Description("1-3 months")]
    Short = 90,
    [Description("3-6 months")]
    Medium = 180,
    [Description("6+ months")]
    Long = 360
}

Is there a good way create a function that would do EnumPrevious(TimeframeType.Short) returns TimeframeType.Now and EnumNext(TimeframeType.Short) would return TimeframeType.Medium?

I already wrote an ugly implementation of EnumNext but I'm not convinced that it is the best way to do so. I'm hoping someone else has already tackled this problem.

public static T EnumNext<T>(T value) where T : struct {
    T[] values = (T[])Enum.GetValues(typeof(T));

    int i;
    for (i = 0; i < values.Length; i++) {
        if (object.Equals(value, values[i])) {
            break;
        }
    }
    if (i >= values.Length - 1) {
        return values[values.Length - 1];
    } else {
        return values[i + 1];
    }
}
+4  A: 

You are trying to solve the wrong problem. This is far too complex for a simple enum to calculate. Refactor the enum to a class and use a comparison interface.

If this route is open to you look at how this could be implemented by a class:

public class TimeFrame: IComparable
{
   private int days;

   public int Days
   {
        set 
        {
             days = value;
        }
   }

   public int CompareTo(object other)
   {
        //see this for implementation -- http://msdn.microsoft.com/en-us/library/system.icomparable.aspx#Mtps_DropDownFilterText
   }


   public string Description
   {
       get code to return the description string , ie "1-3 months"
   }

}
Jimmy McNulty
Ah, that is a much better approach. That class has been an enum for a long time and when adding new functionality I tried to extend instead of refactor. Thanks for the whack on the head :)
DavGarcia
Just wanted to add, there is also an IComparable<T> interface for those copying the code sample above that will let you not have to check the CompareTo's type.
DavGarcia
+2  A: 

Enums in .NET aren't really meant to be ordered, so you shouldn't rely on it. Someone else later might just come and add a value somewhere in the middle that would be out of order. Thus there also isn't such a functionality built in. You can write your own functions (similar to what you have already written) but that's completely up to you. I would also adivse you do the sorting by yourself in your method and not rely on .NET to keep the items "sorted".

Added: That, and I also second the opinion that you should choose another data structure.

Vilx-
A: 

As far as I know, there is not built in way to do this, and your solution looks just dandy - assuming that an enum is the right construct to use here...

I do think that you're trying to do a bit to much with an enum. Perhaps TimeframeType should be a class or should there be a static array of Timeframe data?

(just saw Jimmy's post - looks like we have a similar opinion).

Daniel Paull
A: 

Note this only works if you don't care about the values of the enum and just want them ordered

If you can do change the enum I would do the following

public enum TimeframeType {
    None = 0,
    [Description("1 month")]

    TimeFrameStep = 30,
    [Description("Step from previous to next")]

    Now = None + TimeFrameStep,
    [Description("1-3 months")]

    Short = Now + TimeFrameStep,
    [Description("3-6 months")]

    Medium = Now + TimeFrameStep,
    [Description("6+ months")]

    Long = Medium + TimeFrameStep,
    [Description("12 months")]
}

Then I would loop from Now to Long by incrementing the incrementer by TimeFrameStep.

hhafez
A: 

See the question Enum in C++ like Enum in Ada for information on what Ada does - and, despite what's written in comments there, I don't think it is trivial to provide the same functionality in C, C++, nor (I think) in C# or Java unless those systems provide the help automatically.

Jonathan Leffler