상속 int를 C#에서 열거 형으로 캐스트합니다.




int enum 변환 (17)

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


다음은 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;
    }
}

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

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

문자열에서 :

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

약간 원래 질문에서 멀리지고,하지만 스택 오버플로 질문에 대한 답변을 발견 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 상수를 저장하는 데는 꽤 깔끔한 솔루션처럼 보입니다.


그냥 던져 :

MyEnum e = (MyEnum)3;

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

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

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

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

이것은 위의 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 ()에서 명시 적으로 변환하지 않습니다.


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

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

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

enum Importance
{}

Importance importance;

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

제 경우에는 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 }

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


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

var MyEnumType = typeof(MyEnumType);

그때:

Enum.ToObject(typeof(MyEnum), 3)

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

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

미안하다.


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


 }
}




casting