How to get next (or previous) enum value in C#

后端 未结 24 1903
深忆病人
深忆病人 2020-12-04 10:59

I have an enum which is defined like this:

public enum eRat { A = 0, B=3, C=5, D=8 };

So given value eRat.B, I want to get the

相关标签:
24条回答
  • 2020-12-04 11:20

    Thanks you all, for your inspiration and solutions.

    Here are my results, as an extension.

    public static class Enums
    {
        public static T Next<T>(this T v) where T : struct
        {
            return Enum.GetValues(v.GetType()).Cast<T>().Concat(new[] { default(T) }).SkipWhile(e => !v.Equals(e)).Skip(1).First();
        }
    
        public static T Previous<T>(this T v) where T : struct
        {
            return Enum.GetValues(v.GetType()).Cast<T>().Concat(new[] { default(T) }).Reverse().SkipWhile(e => !v.Equals(e)).Skip(1).First();
        }
    }
    

    use:

    public enum Test { F1, F2, F3 }
    
    public class Program
    {
        public static void Main()
        {
            Test t = Test.F3;   
    
            Console.WriteLine(t);
            Console.WriteLine(t.Next());
            Console.WriteLine(t.Previous());
    
            Console.WriteLine("\n");
    
            t = Test.F1;    
            Console.WriteLine(t);
            Console.WriteLine(t.Next());
            Console.WriteLine(t.Previous());
        }
    }
    

    result:

    F3
    F1
    F2
    
    F1
    F2
    F3
    
    0 讨论(0)
  • 2020-12-04 11:20

    I did something similar with a different enum. It's for a game and the player has the chance to toggle colors.

    public enum PlayerColor {
        Red = 0, Green, Blue, Cyan, Yellow, Orange, Purple, Magenta
    }
    
    public PlayerColor GetNextFreeColor(PlayerColor oldColor) {
    
        PlayerColor newColor = (PlayerColor)((int)(oldColor + 1) % 8);
        return newColor;
    }
    

    This solution worked for me.

    0 讨论(0)
  • 2020-12-04 11:22

    I can think of 2 things:

    • eRat.B+3
    • Enum.Parse(typeof(((int)eRat.B)+3)
    0 讨论(0)
  • 2020-12-04 11:24

    Judging from your description, you don't really want an enum. You're stretching enum beyond its capabilities. Why not create a custom class that exposes the values you need as properties, while keeping them in OrderedDictionary. Then getting a next/previous one would be trivial. --update

    If you want to enumerate differently on the collection based in the context, make that explicit part of your design. Encapsulate the items within a class, and have few methods each returning IEnumerable where, T is your desired type.

    For example

    IEnumerable<Foo> GetFoosByBar()
    IEnumerable<Foo> GetFoosByBaz()
    

    etc...

    0 讨论(0)
  • 2020-12-04 11:24

    You can add and remove integers to an enum to obtain the next value. The only problem is that integer operations on the enum will not check the validity of the enum itself, thus could set "invalid" values.

    But you can combine the ++enum and the Enum.IsDefined() to obtain a simple way to get next and previous values of your enum. This would be inefficient in your case since the integer values are not continuous, but if you have continuous integers then it works nicely, and one can check when the ++enum is out of range. Check the next example.

     public enum level
        {
            a = 0,
            b = 1,
            c = 2,
            d = 3,
            e = 4
        }
    
    private static void Main(string[] args)
        {
            var levelValue = level.a;
            Console.WriteLine(levelValue);
            ++levelValue;
            Console.WriteLine(levelValue);
            ++levelValue;
            Console.WriteLine(levelValue);
            ++levelValue;
            Console.WriteLine(levelValue);
            ++levelValue;
            Console.WriteLine(levelValue);
            ++levelValue;
            Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
            Console.WriteLine(levelValue);
            --levelValue;
            Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
            Console.WriteLine(levelValue);
        }
    

    The output for this would be:

    a
    b
    c
    d
    e
    False
    5
    e
    d
    c
    b
    True
    a
    False
    -1
    
    0 讨论(0)
  • 2020-12-04 11:25

    Seems like an abuse of the enum class to me - but this would do it (assuming that calling Next on the last value would cause wrap-around):

    public static eRat Next(this eRat target)
    {
        var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().SkipWhile(e => e != target).Skip(1);
        if (nextValueQuery.Count() != 0)
        {
            return (eRat)nextValueQuery.First();
        }
        else
        {
            return eRat.A;
        }
    }
    

    And this would give you the previous value on the same basis:

    public static eRat Previous(this eRat target)
    {
        var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().Reverse().SkipWhile(e => e != target).Skip(1);
        if (nextValueQuery.Count() != 0)
        {
            return (eRat)nextValueQuery.First();
        }
        else
        {
            return eRat.D;
        }
    }
    
    0 讨论(0)
提交回复
热议问题