我有一个枚举,其定义如下:
public enum eRat { A = 0, B=3, C=5, D=8 };
Run Code Online (Sandbox Code Playgroud)
所以给定价值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):
Run Code Online (Sandbox Code Playgroud)
现在这太复杂了,对于那些简单的事情.你知道更好的解决方案吗?有点像eRat.B+1或Enum.Next(Erat.B)?
谢谢
hus*_*ayt 59
感谢大家的回答和反馈.得到这么多人我感到很惊讶.看着他们并使用了一些想法,我想出了这个最适合我的解决方案:
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];
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法的优点在于它使用简单且通用.实现为通用扩展方法,您可以通过以下方式在任何枚举上调用它:
return eRat.B.Next();
Run Code Online (Sandbox Code Playgroud)
注意,我使用的是通用扩展方法,因此我不需要在调用时指定类型.Next().
Mar*_*ell 36
可能有点矫枉过正,但是:
eRat value = eRat.B;
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.SkipWhile(e => e != value).Skip(1).First();
Run Code Online (Sandbox Code Playgroud)
或者如果你想要第一个在数值上更大的东西:
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.First(e => (int)e > (int)value);
Run Code Online (Sandbox Code Playgroud)
或者对于下一个更大的数字(我们自己做):
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.Where(e => (int)e > (int)value).OrderBy(e => e).First();
Run Code Online (Sandbox Code Playgroud)
嘿,以LINQ为锤子,这个世界充满了指甲;-p
Ken*_*art 21
你真的需要概括这个问题吗?你能这样做吗?
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ows 12
你正在处理的问题是因为你试图让枚举做一些不应该做的事情.它们应该是类型安全的.允许为枚举分配整数值,以便您可以组合它们,但如果您希望它们表示整数值,请使用类或结构.这是一个可能的替代方案:
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
}
Run Code Online (Sandbox Code Playgroud)
这允许您这样做:
int something = eRat.A + eRat.B;
Run Code Online (Sandbox Code Playgroud)
还有这个
eRat.eRatValue current = eRat.A;
while (current != null)
{
Console.WriteLine(current.Value);
current = current.Next;
}
Run Code Online (Sandbox Code Playgroud)
当你可以从类型安全中受益时,你真的应该只使用枚举.如果您依赖它们来表示类型,请切换到常量或类.
编辑
我建议你看看Enumeration Design上的MSDN页面.第一个最佳做法是:
使用枚举来强类型化参数,属性和返回值,这些值表示值集.
我尽量不去争论教条,所以我不会,但这是你要面对的问题.Microsoft不希望您执行您要执行的操作.他们明确要求你不要做你想做的事.这使你很难做你想做的事情.为了完成您要做的事情,您必须构建实用程序代码以强制它看起来有效.
你已经叫你的解决方案优雅不止一次,它可能是,如果枚举被设计以不同的方式,但由于枚举是它们是什么,你的解决方案是不优雅.我认为室内音乐很优雅,但是如果音乐家没有合适的乐器并且不得不用锯片和水壶演奏Vivaldi,那么它将不再优雅,无论他们作为音乐家的能力如何,或音乐有多好在纸上.
dan*_*die 10
达到"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();
}
}
Run Code Online (Sandbox Code Playgroud)
结果
A = B的
下一个枚举B = C的
下一个枚举C = D的
下一个枚举D = A的下一个枚举
谢谢大家,为您提供灵感和解决方案。
这是我的结果,作为扩展。
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();
}
}
Run Code Online (Sandbox Code Playgroud)
用:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
F3
F1
F2
F1
F2
F3
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49458 次 |
| 最近记录: |