enums 변환 - int를 C#에서 열거 형으로 캐스트합니다.





사용법 배열 (18)


이것은 위의 Tawani의 유틸리티 클래스에서와 같이 generics를 사용하여 dot.NET 4.0에서 부분 일치가있는 대상 열거 형에 정수 또는 문자열을 구문 분석합니다. 불완전한 명령 줄 스위치 변수를 변환하는 데 사용하고 있습니다. enum은 null이 될 수 없으므로 논리적으로 기본값을 제공해야합니다. 다음과 같이 호출 할 수 있습니다.

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

코드는 다음과 같습니다.

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

참고 사항 : 문제는 정수에 대한 것이 었습니다. 아무도 Enum.TryParse ()에서 명시 적으로 변환하지 않습니다.

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




더 이상이 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;



비트 마스크 역할을하는 정수가 있고 [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);
    }
}



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

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 one = 1;
MyEnum e = (MyEnum)one;



Enum Enum 에서 서로 다른 방법으로 캐스트

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = “north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}



문자열에서 :

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

int에서 :

YourEnum foo = (YourEnum)yourInt;

최신 정보:

번호에서 당신은 또한

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






또는 one-liner 대신 확장 메서드를 사용하십시오.

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



제 경우에는 WCF 서비스에서 열거 형을 반환해야했습니다. 또한 enum.ToString ()뿐만 아니라 친숙한 이름이 필요했습니다.

여기에 내 WCF 클래스가 있습니다.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

열거 형에서 설명을 가져 오는 Extension 메서드는 다음과 같습니다.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

이행:

return EnumMember.ConvertToList<YourType>();



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

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

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




입력 데이터를 사용자가 원하는 enum 으로 변환하는 데 도움이 될 수 있습니다. 아래처럼 기본 값이 int 인 enum을 가지고 있다고 가정하십시오. 열거 형의 처음에 기본값을 추가하십시오. 입력 값과 일치하는 항목이 없을 때 헬퍼 메 더드에서 사용됩니다.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

주의 : enum은 기본적으로 int 이므로 int로 값을 파싱하려고합니다. 이처럼 enum을 바이트 유형으로 정의하면 다음과 같습니다.

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

도우미 메서드에서 구문 분석을 변경해야합니다.

int.TryParse(value.ToString(), out  tempType)

byte.TryParse(value.ToString(), out tempType)

입력을 따르는 방법을 확인합니다.

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

미안하다.




때로는 MyEnum 유형의 객체가 있습니다. 처럼

var MyEnumType = typeof(MyEnumType);

그때:

Enum.ToObject(typeof(MyEnum), 3)



완전한 대답을 얻으려면 사람들이 .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();
}



약간 원래 질문에서 멀리지고,하지만 스택 오버플로 질문에 대한 답변을 발견 enum 유용한 int 값을 가져와 . public const int 속성을 사용하여 정적 클래스를 만들어 관련 int 상수를 쉽게 모을 수 있으며이를 사용할 때 int 로 캐스팅 할 필요가 없습니다.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

분명히 일부 열거 형 기능은 손실 될 것이지만 많은 데이터베이스 ID 상수를 저장하는 데는 꽤 깔끔한 솔루션처럼 보입니다.




문자열을 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");



숫자 값의 경우이 값은 무엇이든 상관없이 객체를 반환하므로 더 안전합니다.

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}



enum을 int로 변환하는 대신 다음을 시도하십시오.

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}




c# enums casting