Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在C中获取下一个(或上一个)枚举值#_C#_.net_Enums - Fatal编程技术网

C# 如何在C中获取下一个(或上一个)枚举值#

C# 如何在C中获取下一个(或上一个)枚举值#,c#,.net,enums,C#,.net,Enums,我有一个枚举,其定义如下: public enum eRat { A = 0, B=3, C=5, D=8 }; public enum ItemStatus { New = 0, Draft = 1, Received = 2, Review = 4, Rejected = 8, Approved = 16 } ItemStatus myStatus = ItemStatus.

我有一个枚举,其定义如下:

public enum eRat { A = 0, B=3, C=5, D=8 };
 public enum ItemStatus
    {
        New = 0,
        Draft = 1,
        Received = 2,
        Review = 4,
        Rejected = 8,
        Approved = 16
    }

ItemStatus myStatus = ItemStatus.Draft;
所以给定值
eRat.B
,我想得到下一个值,即
eRat.C

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

Array a=Enum.GetValues(typeof(eRat));
int i=0;
对于(i=0;i
对于这么简单的事情来说,这太复杂了。你知道更好的解决办法吗??类似于
eRat.B+1
Enum.Next(eRat.B)


谢谢

我能想到两件事:

  • eRat.B+3
  • 枚举解析(typeof((int)eRat.B)+3)
var next=(eRat)((int)someRat+3);

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

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

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

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的下一个枚举


可能有点过分了,但是:

eRat value = eRat.B;
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
        .SkipWhile(e => e != value).Skip(1).First();
eRat值=eRat.B;
eRat nextValue=Enum.GetValues(typeof(eRat)).Cast()
.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()
。第一个(e=>(int)e>(int)值);
或者对于下一个更大的数字(自己进行排序):

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

嘿,有了林克作为你的锤子,世界上到处都是钉子;-p

你可以简化它,并将其概括为:

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);
}
给定
brushtyle.NULL
brushtyle.HOLLOW
,返回值将为
brushtyle.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];
}
static T GetNextValue(te)
{
T[]all=(T[])Enum.GetValues(typeof(T));
int i=Array.IndexOf(all,e);
if(i<0)
抛出新的InvalidEnumArgumentException();
如果(i==all.Length-1)
抛出新的ArgumentException(“无更多值”、“e”);
返回所有[i+1];
}

@leppie


您的泛型版本允许您意外地传递一个非枚举值,该值只有在运行时才会被捕获。我最初是作为泛型编写的,但当编译器拒绝
where T:enum
时,我将其取出,并意识到我并没有从泛型中获得多少好处。唯一真正的缺点是您必须将结果转换为返回到您的特定枚举类型。

我同意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;
  }
}
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
}
MyEnum initial=MyEnum.B,next;
对于(int i=((int)initial)+1,i
注意:假设了许多假设:)

您真的需要概括这个问题吗?你能这样做吗

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

您要处理的问题是,您试图让枚举执行它不应该执行的操作。它们应该是类型安全的。允许将整数值指定给枚举,以便可以组合它们,但如果希望它们表示整数值,请使用类或结构。这里有一个可能的替代方案:

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;
  }
}
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;
}
只有在可以从枚举的类型安全性中获益时,才应该使用枚举。如果依赖它们来表示类型,请切换到常量或类

编辑

我建议您查看上的MSDN页面。第一个最佳做法是:

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

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


您不止一次地称您的解决方案为优雅的,如果枚举是以不同的方式设计的,那么可能是这样,但是由于枚举就是它们,所以您的解决方案并不优雅。我认为室内乐是优雅的,但如果音乐家没有合适的乐器,不得不用锯片和水壶演奏维瓦尔第,那么无论他们作为音乐家有多能干,或者音乐在纸面上有多好,室内乐都将不再优雅。

你是不是被一些你无法控制的东西束缚在使用enum上了

如果你不是,我建议使用另一种方法,可能是
字典鼠

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

如果您必须使用枚举,我建议您做一些其他事情:

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

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

从您的描述判断,您并不真正想要一个枚举。您正在将enum扩展到超出其功能范围。为什么不创建一个自定义类,将您需要的值作为属性公开,同时保持它们的有序性呢。 那么,获得下一个/上一个将是微不足道的。 --更新

如果希望根据上下文对集合进行不同的枚举,请将该显式部分作为设计的一部分。 将项封装在类中,并具有fe
IEnumerable<Foo> GetFoosByBar()
IEnumerable<Foo> GetFoosByBaz()
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;
    }
}
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;
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)]; 
   }
} 
A = 1
B = 5
C = 78
D = 30
A = 1
AA = 2
AAA = 34
B = 5
BB = 6
C = 78
CC = 90
D = 30
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();
}
    //===================================================================================
// 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 ];
}
public MyEnum getNext() {
    return this.ordinal() < MyEnum.values().length - 1 ? 
                            MyEnum.values()[this.ordinal() + 1] : 
                            MyEnum.values()[0];
}
//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

}
var nextValue = Enum.GetValues(typeof(EnumT)).Cast<EnumT>().Concat(new[]{default(EnumT)}).SkipWhile(_ => _ != value).Skip(1).First();
 public enum ItemStatus
    {
        New = 0,
        Draft = 1,
        Received = 2,
        Review = 4,
        Rejected = 8,
        Approved = 16
    }

ItemStatus myStatus = ItemStatus.Draft;
myStatus = (ItemStatus)(((int)myStatus) << 1)
myStatus = (ItemStatus)(((int)myStatus) >> 1)
    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);
    }
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;
}
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
 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