我有一个枚举,其定义如下:
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+1
或Enum.Next(Erat.B)
?
谢谢
感谢大家的回答和反馈.得到这么多人我感到很惊讶.看着他们并使用了一些想法,我想出了这个最适合我的解决方案:
public static class Extensions
{
public static T Next(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(Arr, src) + 1;
return (Arr.Length==j) ? Arr[0] : Arr[j];
}
}
这种方法的优点在于它使用简单且通用.实现为通用扩展方法,您可以通过以下方式在任何枚举上调用它:
return eRat.B.Next();
注意,我使用的是通用扩展方法,因此我不需要在调用时指定类型.Next()
.
可能有点矫枉过正,但是:
eRat value = eRat.B; eRat nextValue = Enum.GetValues(typeof(eRat)).Cast() .SkipWhile(e => e != value).Skip(1).First();
或者如果你想要第一个在数值上更大的东西:
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast() .First(e => (int)e > (int)value);
或者对于下一个更大的数字(我们自己做):
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast() .Where(e => (int)e > (int)value).OrderBy(e => e).First();
嘿,以LINQ为锤子,这个世界充满了指甲;-p
你真的需要概括这个问题吗?你能这样做吗?
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; } }
你正在处理的问题是因为你试图让枚举做一些不应该做的事情.它们应该是类型安全的.允许为枚举分配整数值,以便您可以组合它们,但如果您希望它们表示整数值,请使用类或结构.这是一个可能的替代方案:
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不希望您执行您要执行的操作.他们明确要求你不要做你想做的事.这使你很难做你想做的事情.为了完成您要做的事情,您必须构建实用程序代码以强制它看起来有效.
你已经叫你的解决方案优雅不止一次,它可能是,如果枚举被设计以不同的方式,但由于枚举是它们是什么,你的解决方案是不优雅.我认为室内音乐很优雅,但是如果音乐家没有合适的乐器并且不得不用锯片和水壶演奏Vivaldi,那么它将不再优雅,无论他们作为音乐家的能力如何,或音乐有多好在纸上.
达到"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的下一个枚举