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.WriteLine
call 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;
}
}