[c#] int를 C #에서 열거 형으로 캐스트합니다.



Answers

그냥 던져 :

MyEnum e = (MyEnum)3;

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

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

C #에서 enum 으로 int 를 캐스팅 할 수 있습니까?




문자열에서 : (Enum.Parse가 오래되었습니다. Enum.TryParse를 사용하십시오.)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}



다음은 약간 더 나은 확장 방법입니다.

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }






비트 마스크 역할을하는 정수가 있고 [Flags] 열거 형에서 하나 이상의 값을 나타낼 수있는 경우이 코드를 사용하여 개별 플래그 값을 목록으로 구문 분석 할 수 있습니다.

for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1)
{
    // Check to see if the current flag exists in the bit mask
    if ((intValue & flagIterator) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), flagIterator))
            ListOfEnumValues.Add((MyEnum)flagIterator);
    }
}



더 이상이 enum 확장의 일부를 어디에서 얻을지 모르지만 에서 왔습니다. 나는 이것을 유감스럽게 생각한다! 하지만 이걸 가져 와서 Flags로 enum을 수정했습니다. Flags를 사용하는 열거 형의 경우이 작업을 수행했습니다.

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

예:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;



완전한 대답을 얻으려면 사람들이 .NET에서 enum이 어떻게 작동 하는지를 알아야합니다.

어떻게 작동합니까?

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

public enum Foo : short

이 경우 열거 형은 short 데이터 형식에 매핑됩니다. short , 메모리에 단시간 저장되며 캐스트하고 사용할 때 짧은 것으로 간주됩니다.

일리노이 관점에서 볼 때, (보통, 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.EnumBarFlag 가 메모리에서 4 바이트를 BarFlag Foo 가 2를 차지한다는 것을 의미하는 값 유형이라는 것을 지적 BarFlag 합니다. 기본 유형의 크기 (실제로는 더 많습니다. 그것보다 복잡하지만, 헤이 ...).

대답

따라서 열거 형에 매핑 할 정수가있는 경우 런타임은 2 가지 작업 만 수행하면됩니다. 4 바이트를 복사하여 다른 이름 (열거 형 이름)으로 지정해야합니다. 데이터가 값 유형으로 저장되기 때문에 복사가 암시 적입니다. 기본적으로 관리되지 않는 코드를 사용하면 데이터를 복사하지 않고 단순히 enum과 정수를 교환 할 수 있습니다.

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

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

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.WriteLineToString() 호출하면 e2 의 이름이 해석되지 않고 e1 의 이름이 해석됩니다.

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

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

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



다음은 플래그 열거 형 인식 안전 변환 메소드입니다.

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: struct
{
  var enumType = typeof (T);
  if (!enumType.IsEnum)
  {
    throw new ArgumentException("The generic type must be an enum.");
  }
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}



이 코드를 사용하여 int 열을 내 enum으로 캐스팅합니다.

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

나는 그것을 최상의 해결책으로 생각한다.




문자열을 ENUM 또는 int로 상수로 변환하려면 Enum.Parse 함수를 사용해야합니다. 다음은 youtube video https://www.youtube.com/watch?v=4nhx4VwdRDk 입니다. 실제로 문자열을 사용하고 int가 동일하게 적용됩니다.

코드는 다음과 같습니다. "red"는 문자열이고 "MyColors"는 색상 상수가있는 ENUM 색상입니다.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");



Related