【问题标题】:How to get next (or previous) enum value in C#如何在 C# 中获取下一个(或上一个)枚举值
【发布时间】:2010-10-13 03:42:52
【问题描述】:

我有一个这样定义的枚举:

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

所以给定值eRat.B,我想得到下一个是eRat.C

我看到的解决方案是(没有范围检查)

Array a = Enum.GetValues(typeof(eRat));
int i=0 ;
for (i = 0; i < a.GetLength(); i++)
{
       if (a.GetValue(i) == eRat.B)
            break;
}
return (eRat)a.GetValue(i+1):

对于这么简单的事情来说,这太复杂了。你知道更好的解决方案吗?? eRat.B+1Enum.Next(Erat.B) 之类的?

谢谢

【问题讨论】:

  • 这取决于你。但是假设是 A,所以我们不必引发异常。
  • @husayt:代码已更新。现在当你传递“D”时,将返回“A”。

标签: c# .net enums


【解决方案1】:

感谢大家的回答和反馈。我很惊讶得到这么多。看着他们并使用了一些想法,我想出了这个最适合我的解决方案:

public static class Extensions
{

    public static T Next<T>(this T src) where T : struct
    {
        if (!typeof(T).IsEnum) throw new ArgumentException(String.Format("Argument {0} is not an Enum", typeof(T).FullName));

        T[] Arr = (T[])Enum.GetValues(src.GetType());
        int j = Array.IndexOf<T>(Arr, src) + 1;
        return (Arr.Length==j) ? Arr[0] : Arr[j];            
    }
}

这种方法的美妙之处在于它简单且通用。作为通用扩展方法实现,您可以通过这种方式在任何枚举上调用它:

return eRat.B.Next();

注意,我使用的是通用扩展方法,因此我不需要在调用时指定类型,只需.Next()

【讨论】:

  • 主要为我工作。 Windows Phone Silverlight 8.0 上的 struct 显然不存在 Type.IsEnum。删除了类型检查,它工作得很好。
  • 既然可以使用where T : Enum,为什么还要使用struct
【解决方案2】:

可能有点矫枉过正,但是:

eRat value = eRat.B;
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
        .SkipWhile(e => e != value).Skip(1).First();

或者如果你想要第一个数值更大的:

eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
        .First(e => (int)e > (int)value);

或下一个更大的数字(自己进行排序):

eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
        .Where(e => (int)e > (int)value).OrderBy(e => e).First();

嘿,用 LINQ 作为你的锤子,世界上到处都是钉子;-p

【讨论】:

  • +1 "用 LINQ 作为你的锤子" -> 伤害自己不是最快的学习方法吗? ;)
  • 嘿,我知道我在做死灵术 ;-) 但是说到锤子,在使用这样的构造(LINQ)的高性能情况下要小心。每个 LINQ 语句最终都会在内部分配一个列表。觉得很酷,我在一个非常大的项目中使用了这种语法,它很快成为了分配的第一热点。所以有时候,丑陋但干净胜过时髦和酷。
  • @KeithBluestone 不,说每个 LINQ 操作分配一个列表是不正确的;大多数是由迭代器块完成的。需要缓冲的主要是OrderBy和GroupBy。
  • @MarcGravell 点,谢谢。总的来说,我只是想让开发人员意识到,在 LINQ 友好、语义上舒适的引擎盖下,可能隐藏着大量的 List 分配。我 LINQ 粉丝,而且大多数时候,这不是问题;但是写了一些高流量的代码,让我很头疼。
  • 这在eRat value = eRat.D "InvalidOperationException Sequence contains no elements" rextester.com/live/YRGPO87367 时不起作用
【解决方案3】:

真的需要概括这个问题吗?你可以这样做吗?

public void SomeMethod(MyEnum myEnum)
{
    MyEnum? nextMyEnum = myEnum.Next();

    if (nextMyEnum.HasValue)
    {
        ...
    }
}

public static MyEnum? Next(this MyEnum myEnum)
{
    switch (myEnum)
    {
        case MyEnum.A:
            return MyEnum.B;
        case MyEnum.B:
            return MyEnum.C;
        case MyEnum.C:
            return MyEnum.D;
        default:
            return null;
    }
}

【讨论】:

  • +1 简单。构建解决当前需求的东西并继续前进。如有必要,稍后重构。
  • 如果我们假设这是后续重构会有帮助吗?
  • -1。我不喜欢这样,因为这是一个等待发生的维护错误。添加东西的那一天,你想知道为什么你的代码返回 null 确实是糟糕的一天。
【解决方案4】:

你正在处理的问题是因为你试图让一个枚举做它不应该做的事情。它们应该是类型安全的。允许将整数值分配给枚举,以便您可以组合它们,但如果您希望它们表示整数值,请使用类或结构。这是一个可能的替代方案:

public static class eRat
{
    public static readonly eRatValue A;
    public static readonly eRatValue B;
    public static readonly eRatValue C;
    public static readonly eRatValue D;

    static eRat()
    {
        D = new eRatValue(8, null);
        C = new eRatValue(5, D);
        B = new eRatValue(3, C);
        A = new eRatValue(0, B);
    }

    #region Nested type: ERatValue
    public class eRatValue
    {
        private readonly eRatValue next;
        private readonly int value;

        public eRatValue(int value, eRatValue next)
        {
            this.value = value;
            this.next = next;
        }

        public int Value
        {
            get { return value; }
        }

        public eRatValue Next
        {
            get { return next; }
        }

        public static implicit operator int(eRatValue eRatValue)
        {
            return eRatValue.Value;
        }
    }
    #endregion
}

这允许你这样做:

int something = eRat.A + eRat.B;

还有这个

eRat.eRatValue current = eRat.A;
while (current != null)
{
    Console.WriteLine(current.Value);
    current = current.Next;
}

你真的应该只在可以从类型安全中受益时才使用枚举。如果您依赖它们来表示一种类型,请切换到常量或类。

编辑

我建议您查看Enumeration Design 上的 MSDN 页面。第一个最佳实践是:

使用枚举来强类型 参数、属性和返回 表示值集的值。

我尽量不争论教条,所以我不会,但这是你将要面对的问题。 Microsoft 不希望你做你想做的事。他们明确要求你不要做你想做的事。这让你很难做你想做的事。为了完成你想要做的事情,你必须构建实用程序代码来强制它看起来可以工作。

您已经不止一次地调用了您的解决方案优雅,如果枚举是以不同的方式设计的,则可能是这样,但由于枚举就是它们的本质,因此您的解决方案并不优雅。我认为室内乐是优雅的,但如果音乐家没有合适的乐器,不得不用锯片和水壶演奏维瓦尔第,无论他们作为音乐家的能力如何,音乐有多好,它都不再优雅写在纸上。

【讨论】:

  • 看到这个,我希望我能再给它一个 +1。看起来很明显,但我认为我从来没有真正做过这样的事情。
  • 请检查我的答案,我解释了为什么我需要一个枚举。如果您能看到在这种情况下有效的解决方案,我将非常乐意接受。
【解决方案5】:

工作到“C”,因为没有关于“D”之后返回什么的答案。

[update1]:根据 Marc Gravell 的建议更新。

[update2]:根据 husayt 的要求进行更新 - 返回“A”作为“D”的下一个值。

public class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Next enum of A = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.A));
        Console.WriteLine("Next enum of B = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.B));
        Console.WriteLine("Next enum of C = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.C));
    }
}

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

public class eRatEnumHelper
{
    public static eRat GetNextEnumValueOf(eRat value)
    {
        return (from eRat val in Enum.GetValues(typeof (eRat)) 
                where val > value 
                orderby val 
                select val).DefaultIfEmpty().First();
    }
}

结果

A = B 的下一个枚举
B = C的下一个枚举
C = D的下一个枚举
D = A的下一个枚举

【讨论】:

  • 顺便说一句; .Take(1).ToArray()[0] - 可能只是 .First()
  • 天啊。如果另一个人告诉我C#C++ 好,我会给他看这个样本,以表明(1)你不能轻易地在C# 中获得下一个或上一个枚举和(2)你可以做一个@ 987654325@为此。我的天啊! (这不是关于你,而是关于你在C# 中可以做什么:有些人会说随心所欲地做是好事,有些人会说这是邪恶的。恕我直言,这是邪恶的。)
【解决方案6】:

感谢大家的启发和解决方案。

这是我的结果,作为扩展。

using System; 
using System.Linq;

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();
    }
}

使用:

using System; 
using System.Linq;

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());
    }
}

结果:

F3
F1
F2

F1
F2
F3

【讨论】:

  • 别忘了写using System;using System.Linq;
  • @user2513149 感谢您提供的信息,已在此处修复。不知道为什么不见了。
【解决方案7】:

您是否因无法控制的事情而使用枚举?

如果你不是,我建议使用替代方案,可能是Dictionary&lt;string, int&gt; rat;

如果您创建一个Dictionary 并用您的数据填充它,那么枚举它会稍微简单一些。此外,它是更清晰的意图映射——您正在使用此枚举将数字映射到字符串,并且您正在尝试利用该映射。

如果您必须使用枚举,我建议您使用其他方法:

var rats = new List<eRat>() {eRat.A, eRat.B, eRat.C, eRat.D};

只要您按顺序添加值并保持同步,就可以大大简化检索下一个 eRat 的操作。

【讨论】:

    【解决方案8】:

    对于简单的解决方案,您可能只是从枚举中提取数组。

    eRat[] list = (eRat[])Enum.GetValues(typeof(eRat));
    

    那你就可以枚举了

    foreach (eRat item in list)
        //Do something
    

    或查找下一项

    int index = Array.IndexOf<eRat>(list, eRat.B);
    eRat nextItem = list[index + 1];
    

    存储数组比每次需要下一个值时都从枚举中提取要好。

    但如果您想要更漂亮的解决方案,请创建类。

    public class EnumEnumerator<T> : IEnumerator<T>, IEnumerable<T> {
        int _index;
        T[] _list;
    
        public EnumEnumerator() {
            if (!typeof(T).IsEnum)
                throw new NotSupportedException();
            _list = (T[])Enum.GetValues(typeof(T));
        }
        public T Current {
            get { return _list[_index]; }
        }
        public bool MoveNext() {
            if (_index + 1 >= _list.Length)
                return false;
            _index++;
            return true;
        }
        public bool MovePrevious() {
            if (_index <= 0)
                return false;
            _index--;
            return true;
        }
        public bool Seek(T item) {
            int i = Array.IndexOf<T>(_list, item);
            if (i >= 0) {
                _index = i;
                return true;
            } else
                return false;
        }
        public void Reset() {
            _index = 0;
        }
        public IEnumerator<T> GetEnumerator() {
            return ((IEnumerable<T>)_list).GetEnumerator();
        }
        void IDisposable.Dispose() { }
        object System.Collections.IEnumerator.Current {
            get { return Current; }
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return _list.GetEnumerator();
        }
    }
    

    实例化

    var eRatEnum = new EnumEnumerator<eRat>();
    

    迭代

    foreach (eRat item in eRatEnum)
        //Do something
    

    下一个移动

    eRatEnum.Seek(eRat.B);
    eRatEnum.MoveNext();
    eRat nextItem = eRatEnum.Current;
    

    【讨论】:

      【解决方案9】:

      从您的描述来看,您并不真正想要枚举。您正在将枚举扩展到其功能之外。为什么不创建一个自定义类,将您需要的值作为属性公开,同时将它们保存在 OrderedDictionary 中。 然后获得下一个/上一个将是微不足道的。 --更新

      如果您想根据上下文对集合进行不同的枚举,请将该明确的部分作为您的设计。 将项目封装在一个类中,并且每个返回 IEnumerable 的方法很少,其中 T 是您想要的类型。

      例如

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

      等等……

      【讨论】:

      • 好建议 - 而不是超载枚举。
      • 我不明白。 为什么你想在一个枚举上进行 foreach ?您能在这里提供更多背景信息吗?
      • 不在枚举本身。但能够以不同的方式枚举数组成员。我使用枚举作为固定索引器。
      • 检查我的答案,以获得更详细的解释。谢谢。
      【解决方案10】:

      您可以将其简化并概括一下:

      static Enum GetNextValue(Enum e){
          Array all = Enum.GetValues(e.GetType());
          int i = Array.IndexOf(all, e);
          if(i < 0)
              throw new InvalidEnumArgumentException();
          if(i == all.Length - 1)
              throw new ArgumentException("No more values", "e");
          return (Enum)all.GetValue(i + 1);
      }
      

      编辑: 请注意,如果您的枚举包含重复值(同义条目),那么在给定其中一个值的情况下,此(或此处列出的任何其他技术)将失败。例如:

      enum BRUSHSTYLE{
          SOLID         = 0,
          HOLLOW        = 1,
          NULL          = 1,
          HATCHED       = 2,
          PATTERN       = 3,
          DIBPATTERN    = 5,
          DIBPATTERNPT  = 6,
          PATTERN8X8    = 7,
          DIBPATTERN8X8 = 8
      }
      

      给定BRUSHSTYLE.NULLBRUSHSTYLE.HOLLOW,返回值为BRUSHSTYLE.HOLLOW

      更新:泛型版本:

      static T GetNextValue<T>(T e)
      {
        T[] all = (T[]) Enum.GetValues(typeof(T));
        int i = Array.IndexOf(all, e);
        if (i < 0)
          throw new InvalidEnumArgumentException();
        if (i == all.Length - 1)
          throw new ArgumentException("No more values", "e");
        return all[i + 1];
      }
      

      @leppie

      您的通用版本允许您意外传递一个非枚举值,该值仅在运行时被捕获。我最初把它写成一个泛型,但是当编译器拒绝where T : Enum 时,我把它拿出来并意识到我并没有从泛型中获得太多收益。唯一真正的缺点是您必须将结果转换回您的特定枚举类型。

      【讨论】:

      • 加油!泛型,没有泛型!不要偷懒:)
      • @leppie:请看帖子内的评论。
      • 您可以在方法内部添加检查。或者你不必这样做,因为它无论如何都会爆炸:)
      • 我的意思是非泛型版本会在编译时发现你的错误。我总是更喜欢在编译时捕获错误而不是在运行时捕获它们。
      • 为了使通用版本更安全,您可以放置​​“where T : struct”,然后放置“if (!typeof(T).IsEnum) throw new ArgumentException(String.Format("Argumnent {0} is Not an Enum", typeof(T).FullName)); "进一步强制执行
      【解决方案11】:

      希望我的这部分代码对您有所帮助:

      public enum EGroupedBy
      {
          Type,
          InterfaceAndType,
          Alpha,
          _max
      }
      
      private void _btnViewUnit_Click(object sender, EventArgs e)
      {
          int i = (int)GroupedBy;
      
          i = (i + 1) % (int)EGroupedBy._max;
      
          GroupedBy = (EGroupedBy) i;
      
          RefreshUnit();
      }
      

      【讨论】:

      • 我简化为一行 - GroupedBy = (EGroupedBy)(((int)GroupedBy + 1) % (int)EGroupedBy._max);
      【解决方案12】:

      旧帖子,但我有替代解决方案

      //Next with looping    
      public static Enum Next(this Enum input)
      {
          Array Arr = Enum.GetValues(input.GetType());
          int j = Array.IndexOf(Arr, input) + 1;
          return (Arr.Length == j) ? (Enum)Arr.GetValue(0) : (Enum)Arr.GetValue(j);
      }
      
      //Previous with looping
      public static Enum Prev(this Enum input)
      {
         Array Arr = Enum.GetValues(input.GetType());
         int j = Array.IndexOf(Arr, input) - 1;
         return (j == -1) ? (Enum)Arr.GetValue(Arr.Length -1) : (Enum)Arr.GetValue(j);
      }
      

      当你需要使用它时,只需做一个演员表

      BootstrapThemeEnum theme = BootstrapThemeEnum.Info;
      var next = (BootstrapThemeEnum)theme.Next();
      

      我的枚举

      public enum BootstrapThemeEnum
      {
          [Description("white")]
          White = 0,
          [Description("default")]
          Default = 1,
          [Description("info")]
          Info = 2,
          [Description("primary")]
          Primary = 3,
          [Description("success")]
          Success = 4,
          [Description("warning")]
          Warning = 5,
          [Description("danger")]
          Danger = 6,
          [Description("inverse")]
          Inverse = 7
      
      }
      

      【讨论】:

        【解决方案13】:

        我能想到两件事:

        • eRat.B+3
        • Enum.Parse(typeof(((int)eRat.B)+3)

        【讨论】:

        • 因为公共枚举 eRat { A = 0, B=3, C=5, D=8 }; A =0, B=3 所以下一个是+3
        • 是的,但解决方案应该是通用的。它应该适用于任何枚举。在我们的情况下它适用于A吗?我只想要下一个枚举成员。
        • 确实,我显然在睡觉 :P 对不起
        【解决方案14】:

        var next = (eRat)((int)someRat + 3);

        【讨论】:

        • 谢谢,但不是。我们正在寻找通用解决方案。例如,它不适用于 A。
        • @husayt 它适用于 A, (0+3) = B :) - 要使其完全工作,只需将其拆分一点并检查它不会超过最后一个。
        【解决方案15】:

        对我来说,这似乎是对枚举类的滥用——但这可以做到(假设在最后一个值上调用 Next 会导致回绕):

        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;
            }
        }
        

        这将在相同的基础上为您提供先前的值:

        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;
            }
        }
        

        【讨论】:

          【解决方案16】:

          我正在使用这个,非常适合我的。

              //===================================================================================
          // NEXT VALUE IN ENUM 
          // ex: E_CamModes eNew =  kGlobalsVars.eGetNextValue< E_CamModes >( geCmMode );
          public static T eGetNextValue< T >( T eIn ){
              T[] aiAllValues = ( T[] ) Enum.GetValues( typeof( T ));
              int iVal = System.Array.IndexOf( aiAllValues, eIn );
              return aiAllValues[ ( iVal + 1 ) % aiAllValues.Length ];
          }
          

          【讨论】:

            【解决方案17】:

            有一个非常简单的解决方案(如果您可以更改整数值),它专门用于处理数字。您的号码是enum,这不是问题。它仍然是integer(或您分配的任何基础数字类型)。 Enum 只是增加了演员阵容的复杂性。

            假设您的 enum 定义如下:

             public enum ItemStatus
                {
                    New = 0,
                    Draft = 1,
                    Received = 2,
                    Review = 4,
                    Rejected = 8,
                    Approved = 16
                }
            
            ItemStatus myStatus = ItemStatus.Draft;
            

            Enum 使用按位运算。例如:

            myStatus = (ItemStatus)(((int)myStatus) << 1)
            

            myStatus 的结果是:ItemStatus.Received

            您还可以通过将按位运算符从 &lt;&lt; 更改为 &gt;&gt; 来倒退 Enum

            myStatus = (ItemStatus)(((int)myStatus) >> 1)
            

            myStatus 的结果是:ItemStatus.New

            您应该始终添加代码来测试两个方向的“越界”情况。

            您可以在此处了解有关按位运算的更多信息:http://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301

            【讨论】:

            • 有一个更简单的解决方案(如果您可以更改整数值),专门用于处理数字:自然数!如果您使用 1、2、3、4、5... 您可以使用 mystatus++mystatus--。问题是他需要这些数字:0、3、5...
            • 这没有按预期工作刚刚测试过它并返回错误的值。
            【解决方案18】:

            我会接受 Sung Meister 的回答,但这里有一个替代方案:

            MyEnum initial = MyEnum.B, next;
            
            for (int i = ((int) initial) + 1, i < int.MaxValue; i++)
            {
              if (Enum.IsDefined(typeof(MyEnum), (MyEnum) i))
              {
                 next = (MyEnum) i;
                 break;
              }
            }
            

            注意:假设有很多假设:)

            【讨论】:

              【解决方案19】:

              来自 cmets 我有很多问题,例如:“你为什么要以这种方式使用枚举。”既然你们这么多人问,让我给你我的用例,看看你是否同意:

              我有一个固定的项目数组int[n]。根据情况,我想以不同的方式枚举这个数组。所以我定义:

              int[] Arr= {1,2,34,5,6,78,9,90,30};
              enum eRat1 { A = 0, B=3, C=5, D=8 }; 
              enum eRat2 { A, AA,AAA,B,BB,C,C,CC,D }; 
              
              void walk(Type enumType) 
              { 
                 foreach (Type t in Enum.GetValues(enumType)) 
                 { 
                    write(t.ToString() + " = " + Arr[(int)t)]; 
                 }
              } 
              

              并致电walk(typeof(eRAt1))walk(typeof(eRAt2))

              然后我得到所需的输出

              1) 步行(typeof(eRAt1))

              A = 1
              B = 5
              C = 78
              D = 30
              

              2)walk(typeof(eRAt2))

              A = 1
              AA = 2
              AAA = 34
              B = 5
              BB = 6
              C = 78
              CC = 90
              D = 30
              

              这是非常简化的。但我希望,这可以解释。这还有其他一些优点,例如具有 enum.toString()。所以基本上我使用枚举作为索引器。

              所以使用该解决方案我现在可以做这样的事情。

              在 eRat1 中,B 的下一个值是 C,但在 eRat2 中是 BB。 因此,根据我感兴趣的序列,我可以执行 e.next 并且根据 enumType,我将获得 C 或 BB。使用字典如何实现这一目标?

              我认为这是对枚举的一种相当优雅的使用。

              【讨论】:

              • 他们将面临的问题(我认为这是从实用性的角度而非教条的角度)是你试图强制枚举做一些他们专门设计不做的事情(代表一个整数)。它可能感觉很优雅,但您会发现这里讨论的解决方法不会是您的最后一个。
              • 我使用 Enums 进行枚举(这就是他们的名字所暗示的)。我将它们用作索引器,而不仅仅是整数。好的。想象一下棋盘:A,B,C,..,E,F,G,H 一个图形移动 A->C->D->F 另一个 B->C->E->H 第三个 C->A- >B->G 现在枚举是描述所有这些动作的最优雅的方式
              • 我明白你在说什么,但枚举不是用于枚举,即使名称看起来很相似。枚举用于表示无类型的值(即使您可以定义基础类型)。我将更新我的答案以进一步说明
              • 无论如何,如果没有枚举,解决方案会是什么样子??
              • @husayt:数组用整数索引。一组数组索引值应该是一个整数数组,而不是枚举。如果没有枚举,解决方案的强制转换更少,并传递一个索引值的常量数组,以便执行“walk”而不是传递类型参数。披头士不是先说了吗? '所有你需要的是 int'! ...好吧,也许他们没有这么说。
              【解决方案20】:

              我在这里使用这个:

              public MyEnum getNext() {
                  return this.ordinal() < MyEnum.values().length - 1 ? 
                                          MyEnum.values()[this.ordinal() + 1] : 
                                          MyEnum.values()[0];
              }
              

              【讨论】:

              • 我错过了什么吗?我找不到ordinal()
              【解决方案21】:

              LINQ 解决方案不会在最后一个元素上中断,但会再次以默认值继续:

              var nextValue = Enum.GetValues(typeof(EnumT)).Cast<EnumT>().Concat(new[]{default(EnumT)}).SkipWhile(_ => _ != value).Skip(1).First();
              

              【讨论】:

              • 未按预期工作。返回类型不是“下一个”枚举
              【解决方案22】:

              我尝试了第一个解决方案,但它对我不起作用。以下是我的解决方案:

                  public  object NextEnumItem(object currentEnumItem) 
                  {
                      if (!currentEnumItem.GetType().IsEnum) throw new 
                              ArgumentException(String.Format("Argument is not an Enum"));
                      Array Arr = Enum.GetValues(currentEnumItem.GetType());
                      int j = Array.IndexOf(Arr,currentEnumItem) + 1;
                      return (Arr.Length == j) ? currentEnumItem : Arr.GetValue(j);
                  }
              
                  public object PreviousEnumItem(object currentEnumItem)
                  {
                      if (!currentEnumItem.GetType().IsEnum)
                          throw new ArgumentException(String.Format("Argument is not an Enum"));
                      Array Arr = Enum.GetValues(currentEnumItem.GetType());
                      int j = Array.IndexOf(Arr, currentEnumItem) - 1;
                      return (j==-1) ? currentEnumItem : Arr.GetValue(j);
                  }
              

              【讨论】:

                【解决方案23】:

                我用不同的枚举做了类似的事情。这是一款游戏,玩家有机会切换颜色。

                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;
                }
                

                这个解决方案对我有用。

                【讨论】:

                  【解决方案24】:

                  您可以在枚举中添加和删除整数以获得下一个值。唯一的问题是 enum 上的整数运算不会检查 enum 本身的有效性,因此可能会设置“无效”值。

                  但是您可以将 ++enumEnum.IsDefined() 结合起来,以获得获取枚举的下一个和上一个值的简单方法。在您的情况下,这将是低效的,因为整数值不是连续的,但是如果您有连续的整数,那么它可以很好地工作,并且可以检查 ++enum 何时超出范围。检查下一个示例。

                   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);
                      }
                  

                  这个的输出是:

                  a
                  b
                  c
                  d
                  e
                  False
                  5
                  e
                  d
                  c
                  b
                  True
                  a
                  False
                  -1
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2021-04-29
                    • 1970-01-01
                    • 2018-11-05
                    • 1970-01-01
                    • 2014-10-09
                    • 1970-01-01
                    • 2016-07-27
                    • 2010-09-11
                    相关资源
                    最近更新 更多