[c#] 열거 형에 int를 캐스팅하는 방법?

C #에서 int캐스트를 어떻게 캐스트 할 수 enum있습니까?



답변

문자열에서 :

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}

정수에서 :

YourEnum foo = (YourEnum)yourInt;

최신 정보:

번호에서 당신은 또한 할 수 있습니다

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);


답변

그냥 캐스트 :

MyEnum e = (MyEnum)3;

Enum.IsDefined 사용하여 범위 내에 있는지 확인할 수 있습니다 .

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }


답변

또는 한 줄짜리 대신 확장 방법을 사용하십시오.

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

용법:

Color colorEnum = "Red".ToEnum<Color>();

또는

string color = "Red";
var colorEnum = color.ToEnum<Color>();


답변

완전한 대답을 얻으려면 사람들은 열거 형이 .NET에서 내부적으로 어떻게 작동하는지 알아야합니다.

작동 원리

.NET의 열거 형은 값 집합 (필드)을 기본 유형 (기본값은 int)에 매핑하는 구조입니다 . 그러나 실제로 열거 형에 매핑되는 정수 유형을 선택할 수 있습니다.

public enum Foo : short

이 경우 열거 형은 short데이터 유형에 매핑 되므로 메모리에 짧게 저장되어 캐스팅하고 사용할 때 짧게 작동합니다.

IL 관점에서 보면 (normal, int) 열거 형은 다음과 같습니다.

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

여기서 주목해야 할 value__것은 열거 형 값과 별도로 저장 된다는 것 입니다. Foo위 열거 형의 경우 유형 value__은 int16입니다. 이것은 기본적으로 유형이 일치 하는 한 원하는 것을 열거 형에 저장할 수 있음을 의미합니다 .

이 시점에서 나는 이것이 System.Enum값 유형 이라는 것을 지적하고 싶습니다 . 이것은 기본적으로 BarFlag메모리에서 4 바이트를 Foo차지하고 2를 차지 한다는 것을 의미합니다 -예를 들어 기본 유형의 크기 (실제로는 그보다 더 복잡하지만 야…).

대답

따라서 열거 형에 매핑하려는 정수가있는 경우 런타임은 두 가지 작업 만 수행하면됩니다 .4 바이트를 복사하고 다른 이름 (열거 이름)을 지정하십시오. 데이터는 값 유형으로 저장되므로 복사는 암시 적입니다. 이는 기본적으로 관리되지 않는 코드를 사용하는 경우 데이터를 복사하지 않고 열거 형과 정수를 간단히 교환 할 수 있음을 의미합니다.

안전을 기하기 위해 기본 유형이 동일하거나 암시 적으로 변환 가능하다는 것을 알고 열거 형 값이 있는지 확인 하는 것이 가장 좋습니다 (기본적으로 확인되지 않음).

이것이 어떻게 작동하는지 보려면 다음 코드를 시도하십시오.

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

캐스팅 e2도 작동합니다! 위의 컴파일러 관점에서 이것은 의미가 있습니다. value__필드는 단순히 5 또는 6으로 채워지고 Console.WriteLinecall ToString()일 때 이름 e1은 확인 e2되지 않지만 의 이름은 확인 됩니다.

이것이 의도 한 것이 아닌 Enum.IsDefined(typeof(MyEnum), 6)경우 캐스팅하는 값이 정의 된 열거 형에 매핑되는지 확인하는 데 사용 하십시오.

또한 컴파일러가 실제로 이것을 확인하더라도 기본 유형의 열거 형에 대해 명시 적입니다. 나는 길을 놀라게하지 않기 위해 이것을하고 있습니다. 이러한 놀라움을 실제로보기 위해 다음 코드를 사용할 수 있습니다 (실제로 데이터베이스 코드에서 이런 일이 많이 발생하는 것을 보았습니다).

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}


답변

다음 예제를 보자.

int one = 1;
MyEnum e = (MyEnum)one;


답변

이 코드를 사용하여 정수에 int를 캐스팅하고 있습니다.

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

최선의 해결책이라고 생각합니다.


답변

아래는 Enums에 대한 유용한 유틸리티 클래스입니다.

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value)
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}