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)
[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