web-dev-qa-db-ja.com

列挙型の最大値を取得する

列挙型の最大値を取得するにはどうすればよいですか?

133
jdelator

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

...列挙値の一部が負の場合に機能します。

194
Matt Hamilton

マットの答えに同意します。最小および最大整数値だけが必要な場合は、次のようにできます。

最大:

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

最小:

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

Matt Hamiltonの答えによれば、そのためのExtensionメソッドを作成することを考えました。

ValueTypeはジェネリック型パラメーターの制約として受け入れられないため、TEnumに制限するより良い方法は見つかりませんでしたが、次のとおりです。

どんなアイデアでも大歓迎です。

PS。私のVB暗黙性を無視してください、この方法でVBを使用するのが大好きです。これがVBの強さです。 VBが大好きです。

Howeva、ここにあります:

C#:

static void Main(string[] args)
{
    MyEnum x = GetMaxValue<MyEnum>();
}

public static TEnum GetMaxValue<TEnum>() 
    where TEnum : IComparable, IConvertible, IFormattable
    //In C#>=7.3 substitute with 'where TEnum : Enum', and remove the following check:
{
    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
20
Shimmy

これはわずかですが、列挙型の実際の最大値はInt32.MaxValueです(intから派生した列挙型であると仮定)。実際にその値を持つメンバーを宣言したかどうかに関係なく、Int32値を列挙型にキャストすることは完全に合法です。

法的:

enum SomeEnum
{
    Fizz = 42
}

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

別の時間を試した後、私はこの拡張メソッドを手に入れました:

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

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);
        }
    }
5
Eric Feng

C#については、Matthew J Sullivanと合意しました。

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

なぜ誰かが使用したいのか本当に分かりません:

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

... Word-for-Wordのように、意味的に言えば、それはあまり意味をなさないように思われますか? (常に異なる方法があるのは良いことですが、後者には利点がありません。)

4
Engineer

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   

それを実行しています...

> Foo = |と入力しますフィズ= 3 | Bang = 2 
> val ToSeq: 'A-> seq <' B> when 'A:enum <' B> 
> val FooMax:Foo = Fizz 

when 'A : enum<'B>は、コンパイラーによる定義には必要ありませんが、有効な列挙型であっても、ToSeqの使用には必要です。

2
Stephen Hosking

System.Enumには列挙型に関する情報を取得するためのメソッドがあります。

したがって、Visual StudioのVB.Netプロジェクトでは、「System.Enum」と入力できます。そして、インテリセンスはあらゆる種類の良さをもたらします。

特に1つのメソッドは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")

'''''''
2

すべての状況で使用できるわけではありませんが、私は自分で最大値を定義することがよくあります。

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

もちろん、列挙型でカスタム値を使用する場合、これは機能しませんが、多くの場合、簡単な解決策になる可能性があります。

0