繁体   English   中英

获取枚举的最大值

[英]Getting the max value of an enum

你如何获得枚举的最大值?

Enum.GetValues() 似乎按顺序返回值,因此您可以执行以下操作:

// 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();

...当您的某些枚举值为负时,这将起作用。

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

最大值:

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

最低:

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

根据马特汉密尔顿的回答,我想为它创建一个扩展方法。

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

任何想法将不胜感激。

附注。 请忽略我的 VB 隐性,我喜欢以这种方式使用 VB,这就是 VB 的优势,这就是我喜欢 VB 的原因。

Howeva,这里是:

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

这有点挑剔,但任何enum的实际最大值是Int32.MaxValue (假设它是从int派生的enum )。 将任何Int32值转换为 any enum是完全合法的,无论它是否实际声明了具有该值的成员。

法律:

enum SomeEnum
{
    Fizz = 42
}

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

又试了一次,我得到了这个扩展方法:

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

使用 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);
        }
    }

与 Matthew J Sullivan 一致,对于 C#:

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

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

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

...逐字逐句,从语义上讲,它似乎没有多大意义? (有不同的方式总是好的,但我没有看到后者的好处。)

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

因此,在 Visual Studio 的 VB.Net 项目中,我可以键入“System.Enum”。 智能感知带来了各种各样的好处。

一种特别的方法是 System.Enum.GetValues(),它返回枚举值的数组。 一旦你有了数组,你应该能够做任何适合你特定情况的事情。

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

VB.Net 代码片段:

'''''''

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

'''''''

当我需要枚举的最小值和最大值时,我使用了以下内容。 我只是将最小值设置为枚举的最低值,将最大值设置为枚举中的最大值作为枚举值本身。

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!");
}

在 F# 中,使用辅助函数将枚举转换为序列:

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 的任何使用都是必需的,即使是有效的枚举类型也是如此。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM