열거 형의 최대 값 얻기


148

열거 형의 최대 값을 어떻게 얻습니까?



1
컴파일러가 Reflection 호출을 사용하는 대신 이것을 처리 할 수 ​​있다고 생각합니다. 이 정보에 대해 컴파일 타임 방법을 사용한 답변은 투표권을 받았습니다.
palswim

답변:


214

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

... 열거 형 값 중 일부가 음수 일 때 작동합니다.


3
좋은. "배열의 요소는 열거 상수의 이진 값으로 정렬됩니다." 에서 msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx
TheSoftwareJedi

2
나는 이것이 실제로 부족하다고 생각했지만 우아한 해결책이 주어 졌다고 생각하면서 내 머리를 때렸다. 또한 열거 형 값을 얻으려면 나중에 Convert.ToInt32 ()를 사용하십시오. 이것은 구글 결과입니다.
jdelator

54
LINQ를 사용하려면 Max ()를 사용하는 것이 더 명확하고 "seems to"에 의존하지 않는 이유는 무엇입니까?
Marc Gravell

3
열거 형의 값이 음수가 아닌 경우에만 더 잘 수행됩니다.
ICR

4
Max ()에도 투표합니다. 마지막은 () 열거가 부정적인하지 보면 실패 여기
AZ합니다.

42

Matt의 답변에 동의합니다. min 및 max int 값만 필요한 경우 다음과 같이 수행 할 수 있습니다.

최고:

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

최저한의:

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

21

Matt Hamilton의 답변에 따르면 Extension 메서드를 만드는 방법을 생각했습니다.

이후 ValueType제네릭 형식 매개 변수 제약 조건으로 인정되지 않는다, 나는 제한하는 더 나은 방법을 찾을 수 없습니다 TEnum하지만 다음을.

어떤 아이디어라도 정말로 감사하겠습니다.

추신. 내 VB 암시성을 무시하십시오. 이런 식으로 VB를 사용하는 것이 좋습니다. 이것이 VB의 강점이며 VB를 좋아하는 이유입니다.

Howeva, 여기 있습니다 :

씨#:

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

이에 대해서는 stackoverflow.com/questions/79126/… 를 참조하십시오 . if (! type.IsEnum)
콘크리트 가넷

당신은 또한 "구조체"를 추가 할 수있는 곳은가 치 형이지만 열거이에 제한하지 내가 무엇을 사용되도록해야합니다으로 : 여기서 T : 구조체에서 IComparable, IFormattable
jdawiz

2
답변을 업데이트 할 수 있습니다. C # 7.3에서는 실제로 확장 방법을 수행하고 구조체 대신 Enum 유형으로 제한 할 수도 있습니다.
Nordes

이것은 확장 방법이 아닙니다. 그러나 좋은 유틸리티 방법.
Ray

14

이것은 약간 이질적이지만 실제 최대 값은 enum입니다 Int32.MaxValue(에서 enum파생 된 것으로 가정 int). 모든 Int32가치를 어떤 가치에도 적용하는 것은 합법적입니다enum실제로 해당 값을 가진 멤버를 선언했는지 여부에 관계없이 입니다.

적법한:

enum SomeEnum
{
    Fizz = 42
}

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

미친 값이 제공 될 때 Integer 변수를 반환 된 열거 형으로 설정하는 것이 유형 불일치로 실패하는 경우가 있었으므로 대신 Long을 사용하는 것이 가장 좋습니다 (오류가 제대로 잡히지 않으면!).
AjV Jsy

9

다른 시간을 시도한 후에이 확장 방법을 얻었습니다.

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

5

마지막 기능을 사용하면 최대 값을 얻을 수 없습니다. "최대"기능을 사용하십시오. 처럼:

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

4

Matthew J Sullivan과의 C # 동의 :

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

왜 누군가가 사용하고 싶어하는지 잘 모르겠습니다.

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

... 단어 적으로 말하면 의미 적으로 말하면, 그다지 의미가없는 것 같습니까? (항상 다른 방법을 사용하는 것이 좋지만 후자에는 이점이 없습니다.)


4
GetUpperBound를 사용하면 나를 위해 개수 (40이 아닌 4)를 반환합니다. MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe

좋은 캐치, 나는 그것을 알아 차리지 못했다. 따라서이 버전은 표준 자동 열거에는 적합하지만 사용자 정의 값이있는 열거에는 적합하지 않습니다. 우승자는 해밀턴 씨로 남아 있습니다. :)
엔지니어

GetUpperBound는 Enum에 비트 값이있을 때 좋습니다. (즉, 1, 2, 4, 8 등). 예를 들어 단위 테스트를 작성하는 경우 Math.Pow (2, Enum.GetValues ​​(typeof (MyEnum)). GetUpperBound (0))와 같은 많은 반복 작업을 원할 것입니다.
WEFX

열거 형의 값 수에 대한 길이에 어떤 문제가 있습니까? 간단할수록 좋습니다. (이것이 원래의 질문에 답하는 것은 아닙니다.)
Ian Goldby

2

System.Enum 아래에 열거 된 유형에 대한 정보를 얻는 방법이 있습니다.

따라서 Visual Studio의 VB.Net 프로젝트에서 "System.Enum"을 입력 할 수 있습니다. 그리고 지능은 모든 종류의 선을 가져옵니다.

특히 한 가지 방법은 System.Enum.GetValues ​​()이며 열거 된 값의 배열을 반환합니다. 어레이를 확보 한 후에는 특정 상황에 적합한 모든 것을 수행 할 수 있어야합니다.

필자의 경우 열거 된 값은 0에서 시작하여 숫자를 건너 뛰지 않았으므로 열거 형의 최대 값을 얻으려면 배열에 몇 개의 요소가 있는지 알아야합니다.

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

'''''''

어레이에 틈이 있으면 작동하지 않습니다. 요소 인덱스는 해당 인덱스에 저장된 값과 같기 때문에 우연히도 작동합니다. GetUpperBound()에 의해 반환 된 배열에서 가능한 가장 높은 인덱스 를 검색합니다 GetValues().
JensG 2016 년

2

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 : enum <'B> 인 경우 'A-> seq <'B>
> val FooMax : Foo = Fizz

when 'A : enum<'B>정의에 대한 컴파일러에 의해 필요하지 않지만에도 유효한 열거 형으로, ToSeq의 사용이 필요합니다.


1

모든 상황에서 사용할 수는 없지만 종종 최대 값을 직접 정의합니다.

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

물론 열거 형에서 사용자 정의 값을 사용하면 작동하지 않지만 종종 쉬운 해결책 일 수 있습니다.


1

열거 형의 최소 및 최대 값이 필요할 때 다음을 사용했습니다. 나는 열거 형의 가장 낮은 값과 같은 최소값을 열거하고 열거 형의 값 자체와 같은 최대 값을 열거의 최대 값과 동일하게 설정했습니다.

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!");
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.