문제

C #에서 intenum로 캐스팅하려면 어떻게해야하나요?

도움이 되었습니까?

해결책

문자열에서 : 라코 디스

정수에서 : 라코 디스

업데이트 :

전화 번호로도 가능합니다 라코 디스

다른 팁

또는 한 줄 대신 확장 방법을 사용하세요. 라코 디스

사용 : 라코 디스

또는 라코 디스

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

작동 원리

.NET의 열거 형은 일련의 값 (필드)을 기본 유형 (기본값은 int)으로 매핑하는 구조입니다. 그러나 실제로 열거 형이 매핑하는 정수 유형을 선택할 수 있습니다. 라코 디스

이 경우 enum은 short 데이터 유형에 매핑됩니다. 즉, 메모리에 short로 저장되고 캐스팅 및 사용할 때 short로 작동합니다.

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

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

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

답변

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

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

작동 방식을 확인하려면 다음 코드를 시도하세요. 라코 디스

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

그게 의도 한 것이 아니라면 Enum.IsDefined(typeof(MyEnum), 6)를 사용하여 캐스팅하려는 값이 정의 된 열거 형에 매핑되는지 확인합니다.

또한 컴파일러가 실제로 이것을 확인하더라도 enum의 기본 유형에 대해 명시 적입니다. 나는이 과정에서 어떤 놀라움도 겪지 않도록하기 위해이 일을하고 있습니다. 이러한 놀라움이 실제로 작동하는지 확인하려면 다음 코드를 사용할 수 있습니다 (실제로 데이터베이스 코드에서 이러한 일이 많이 발생하는 것을 보았습니다). 라코 디스

다음 예를 살펴보세요.
라코 디스

이 코드를 사용하여 int를 enum으로 캐스트합니다. 라코 디스

최고의 솔루션입니다.

다음은 Enum을위한 멋진 유틸리티 클래스입니다. 라코 디스

숫자 값의 경우 어떤 경우에도 객체를 반환하므로 더 안전합니다. 라코 디스

4.0 .NET 프레임 워크를 사용할 준비가 되었다면 새로운 Enum.TryParse () 매우 유용하고 [Flags] 속성과 잘 작동하는 함수입니다. Enum.TryParse 메서드 (String, TEnum %)

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

여기에서는 enum의 기본 유형이 부호있는 32 비트 정수라고 가정합니다.다른 숫자 유형이라면 해당 유형의 비트를 반영하도록 하드 코딩 된 32를 변경해야합니다 (또는 Enum.GetUnderlyingType()를 사용하여 프로그래밍 방식으로 파생).

때로는 MyEnum 유형에 대한 개체가 있습니다.좋아요 라코 디스

다음 : 라코 디스

다음은 플래그 열거 형 안전한 변환 방법입니다. 라코 디스

enter image description here

To convert a string to ENUM or int to ENUM constant we need to use Enum.Parse function. Here is a youtube video https://www.youtube.com/watch?v=4nhx4VwdRDk which actually demonstrate's with string and the same applies for int.

The code goes as shown below where "red" is the string and "MyColors" is the color ENUM which has the color constants.

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

Slightly getting away from the original question, but I found an answer to Stack Overflow question Get int value from enum useful. Create a static class with public const int properties, allowing you to easily collect together a bunch of related int constants, and then not have to cast them to int when using them.

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

Obviously, some of the enum type functionality will be lost, but for storing a bunch of database id constants, it seems like a pretty tidy solution.

This parses integers or strings to a target enum with partial matching in dot.NET 4.0 using generics like in Tawani's utility class above. I am using it to convert command-line switch variables which may be incomplete. Since an enum cannot be null, you should logically provide a default value. It can be called like this:

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

Here's the code:

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

FYI: The question was about integers, which nobody mentioned will also explicitly convert in Enum.TryParse()

From a string: (Enum.Parse is out of Date, use Enum.TryParse)

enum Importance
{}

Importance importance;

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

Following is slightly better extension method

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

In my case, I needed to return the enum from a WCF service. I also needed a friendly name, not just the enum.ToString().

Here's my WCF Class.

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

Here's the Extension method that gets the Description from the Enum.

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

Implementation:

return EnumMember.ConvertToList<YourType>();

Different ways to cast to and from 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);


 }
}

I don't know anymore where I get the part of this enum extension, but it is from stackoverflow. I am sorry for this! But I took this one and modified it for enums with Flags. For enums with Flags I did this:

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

Example:

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

It can help you to convert any input data to user desired enum. Suppose you have an enum like below which by default int. Please add a Default value at first of your enum. Which is used at helpers medthod when there is no match found with input value.

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

N.B: Here I try to parse value into int, because enum is by default int If you define enum like this which is byte type.

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

You need to change parsing at helper method from

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

to

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

I check my method for following inputs

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

sorry for my english

Here's an extension method that casts Int32 to Enum.

It honors bitwise flags even when the value is higher than the maximum possible. For example if you have an enum with possibilities 1, 2, and 4, but the int is 9, it understands that as 1 in absence of an 8. This lets you make data updates ahead of code updates.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

the easy and clear way for casting an int to enum in c#:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

You simply use Explicit conversion Cast int to enum or enum to int

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((int)Number.three); //Output=3

            Console.WriteLine((Number)3);// Outout three
            Console.Read();
        }

        public enum Number 
        {
            Zero = 0,
            One = 1,
            Two = 2,
            three = 3           
        }
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top