列挙型の最大値を取得するにはどうすればよいですか?
11 に答える
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();
...列挙値の一部が負の場合に機能します。
マットの答えに同意します。最小値と最大値の int 値だけが必要な場合は、次のように実行できます。
最大:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
最小:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
Matt Hamilton の回答によると、そのための Extension メソッドを作成することを考えました。
ValueType
はジェネリック型パラメーターの制約として受け入れられないため、次のように制限するより良い方法は見つかりませんでしT
たEnum
。
どんなアイデアでも大歓迎です。
PS。私の 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
これは少し厄介ですが、 any の実際の最大値enum
は(から派生したものInt32.MaxValue
であると仮定して) です。実際にその値を持つメンバーを宣言したかどうかに関係なく 、任意の値をany にキャストすることは完全に合法です。enum
int
Int32
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 関数を使用して最大値を取得できませんでした。「最大」機能を使用できます。お気に入り:
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」と入力できます。インテリセンスはあらゆる種類の善をもたらします。
特に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")
'''''''
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 | 強打 = 2 > val ToSeq : 'A -> seq<'B> when 'A : enum<'B> > val FooMax : Foo = フィズ
はwhen 'A : enum<'B>
、コンパイラによる定義には必要ありませんが、有効な列挙型であっても、ToSeq を使用するために必要です。