获取枚举的最大值

如何得到枚举的最大值?

109823 次浏览

Enum.GetValue ()似乎按顺序返回值,所以您可以这样做:

// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}


// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();

剪辑

对于那些不愿意阅读评论的人: 你也可以这样做:

var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();

当一些枚举值为负时,它就会工作。

这有点吹毛求疵,但任何 enum的实际最大值都是 Int32.MaxValue(假设它是从 int派生出来的 enum)。将任何 Int32值强制转换为任何 enum都是完全合法的,无论它是否实际声明了具有该值的成员。

法律:

enum SomeEnum
{
Fizz = 42
}


public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}

根据 Matt Hamilton 的回答,我想为它创建一个扩展方法。

由于 ValueType不被接受为泛型类型参数约束,因此我没有找到更好的方法将 T限制为 Enum,但是采用了以下方法。

任何想法都可以。

附言。请忽略我的 VB 隐含性,我喜欢这样使用 VB,这就是 VB 的优点,也是我喜欢 VB 的原因。

然而,事情是这样的:

C # :

static void Main(string[] args)
{
MyEnum x = GetMaxValue<MyEnum>(); //In newer versions of C# (7.3+)
MyEnum y = GetMaxValueOld<MyEnum>();
}


public static TEnum GetMaxValue<TEnum>()
where TEnum : Enum
{
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();
}


//When C# version is smaller than 7.3, use this:
public static TEnum GetMaxValueOld<TEnum>()
where TEnum : IComparable, IConvertible, IFormattable
{
Type type = typeof(TEnum);


if (!type.IsSubclassOf(typeof(Enum)))
throw new
InvalidCastException
("Cannot cast '" + type.FullName + "' to System.Enum.");


return (TEnum)Enum.ToObject(type, Enum.GetValues(type).Cast<int>().Last());
}






enum MyEnum
{
ValueOne,
ValueTwo
}

VB:

Public Function GetMaxValue _
(Of TEnum As {IComparable, IConvertible, IFormattable})() As TEnum


Dim type = GetType(TEnum)


If Not type.IsSubclassOf(GetType([Enum])) Then _
Throw New InvalidCastException _
("Cannot cast '" & type.FullName & "' to System.Enum.")


Return [Enum].ToObject(type, [Enum].GetValues(type) _
.Cast(Of Integer).Last)
End Function

有一些方法可以获取 System.Enum 下的枚举类型的信息。

因此,在 Visual Studio 中的一个 VB.Net 项目中,我可以键入“ System”。Enum”智慧带来了各种各样的美好。

其中一个特别的方法是 System。Enum.GetValue () ,它返回枚举值的数组。一旦你得到了数组,你应该能够做任何适合你的特殊情况。

在我的例子中,枚举值从零开始,没有跳过任何数字,因此要获得枚举的最大值,我只需要知道数组中有多少元素。

网络代码片段:

'''''''


Enum MattType
zerothValue         = 0
firstValue          = 1
secondValue         = 2
thirdValue          = 3
End Enum


'''''''


Dim iMax      As Integer


iMax = System.Enum.GetValues(GetType(MattType)).GetUpperBound(0)


MessageBox.Show(iMax.ToString, "Max MattType Enum Value")


'''''''

使用“ Last”函数无法得到最大值。使用“ max”函数可以。比如:

 class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };


static void Main(string[] args)
{
TestMaxEnumValue(typeof(enum1));
TestMaxEnumValue(typeof(enum2));
TestMaxEnumValue(typeof(enum3));
}


static void TestMaxEnumValue(Type enumType)
{
Enum.GetValues(enumType).Cast<Int32>().ToList().ForEach(item =>
Console.WriteLine(item.ToString()));


int maxValue = Enum.GetValues(enumType).Cast<int>().Max();
Console.WriteLine("The max value of {0} is {1}", enumType.Name, maxValue);
}
}

在另一次尝试之后,我得到了这个扩展方法:

public static class EnumExtension
{
public static int Max(this Enum enumType)
{
return Enum.GetValues(enumType.GetType()).Cast<int>().Max();
}
}


class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };


static void Main(string[] args)
{
Console.WriteLine(enum1.one.Max());
}
}

与马修 · J · 沙利文(Matthew J Sullivan)一致,C # :

   Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);

我真的不知道为什么会有人想用:

   Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();

... 逐字逐句,从语义上讲,似乎没有多大意义?(有不同的方法总是好的,但我不认为后者有什么好处。)

在 F # 中,使用一个 helper 函数将枚举转换为一个序列:

type Foo =
| Fizz  = 3
| Bang  = 2


// Helper function to convert enum to a sequence. This is also useful for iterating.
// stackoverflow.com/questions/972307/can-you-loop-through-all-enum-values-c
let ToSeq (a : 'A when 'A : enum<'B>) =
Enum.GetValues(typeof<'A>).Cast<'B>()


// Get the max of Foo
let FooMax = ToSeq (Foo()) |> Seq.max

运行它..。

> type Foo = | Fizz = 3 | Bang = 2
> val ToSeq : 'A -> seq<'B> when 'A : enum<'B>
> val FooMax : Foo = Fizz

编译器对于定义不需要 when 'A : enum<'B>,但是对于 ToSeq 的任何使用都需要 when 'A : enum<'B>,甚至对于有效的枚举类型也是如此。

我同意马特的回答。如果只需要 min 和 max int 值,那么可以按照如下方式进行。

最高:

Enum.GetValues(typeof(Foo)).Cast<int>().Max();

最低限度:

Enum.GetValues(typeof(Foo)).Cast<int>().Min();

它并非在所有情况下都可用,但我经常自己定义最大值:

enum Values {
one,
two,
tree,
End,
}


for (Values i = 0; i < Values.End; i++) {
Console.WriteLine(i);
}


var random = new Random();
Console.WriteLine(random.Next((int)Values.End));

当然,当您在枚举中使用自定义值时,这种方法不起作用,但通常这是一种简单的解决方案。

当需要枚举的 min 和 max 值时,我使用了以下方法。 我只是设置了一个 min 等于枚举的最低值,一个 max 等于枚举中的最高值作为枚举值本身。

public enum ChannelMessageTypes : byte
{
Min                 = 0x80, // Or could be: Min = NoteOff
NoteOff             = 0x80,
NoteOn              = 0x90,
PolyKeyPressure     = 0xA0,
ControlChange       = 0xB0,
ProgramChange       = 0xC0,
ChannelAfterTouch   = 0xD0,
PitchBend           = 0xE0,
Max                 = 0xE0  // Or could be: Max = PitchBend
}


// I use it like this to check if a ... is a channel message.
if(... >= ChannelMessageTypes.Min || ... <= ChannelMessages.Max)
{
Console.WriteLine("Channel message received!");
}