답변:
문자열에서 :
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);
var result = Enum.TryParse(yourString, out yourEnum)
요즘 실제로 사용해야 합니다 (결과를 확인하여 변환이 실패했는지 확인).
Enum.Parse
추가하여 대소 문자를 구분하지 않을 수도 있습니다 true
.YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
그냥 캐스트 :
MyEnum e = (MyEnum)3;
Enum.IsDefined 사용하여 범위 내에 있는지 확인할 수 있습니다 .
if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Enum.IsDefined
, 위험 할 수 있습니다 : msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
IsDefined
입력 값을 확인, 당신은 통과 할 것입니다 나중에 새로운 열거 값을 추가 사람에 취약 자신을 떠나 IsDefined
새로운 이후 체크 ( 값이 새 코드에 존재하지만 사용자가 작성한 원래 코드에서 작동하지 않을 수 있습니다. 따라서 코드에서 처리 할 수있는 열거 형 값을 명시 적으로 지정하는 것이 더 안전합니다.
또는 한 줄짜리 대신 확장 방법을 사용하십시오.
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>();
System.String
네임 스페이스 오염처럼 보입니다
완전한 대답을 얻으려면 사람들은 열거 형이 .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
! = 때문에 short
던질 것입니다 (unboxing 실패). 그렇게 object o = (short)5;
하면 유형이 일치하기 때문에 작동합니다. 그것은 범위에 관한 것이 아니라 실제로 유형에 관한 것입니다.
이 코드를 사용하여 정수에 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;
}
}
숫자 값의 경우 다음에 관계없이 객체를 반환하므로 더 안전합니다.
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;
}
}
4.0 .NET Framework를 사용할 준비가되면 매우 유용하고 [Flags] 특성과 잘 작동 하는 새로운 Enum.TryParse () 함수가 있습니다. Enum.TryParse 메서드 (String, TEnum %)를 참조하십시오.
비트 마스크 역할을하며 [Flags] 열거에서 하나 이상의 값을 나타낼 수있는 정수가있는 경우이 코드를 사용하여 개별 플래그 값을 목록으로 구문 분석 할 수 있습니다.
for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
// Determine the bit value (1,2,4,...,Int32.MinValue)
int bitValue = 1 << flagIterator;
// Check to see if the current flag exists in the bit mask
if ((intValue & bitValue) != 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), bitValue))
Console.WriteLine((MyEnum)bitValue);
}
}
이것은의 기본 유형이 enum
부호있는 32 비트 정수 라고 가정합니다 . 다른 숫자 유형 인 경우 해당 유형의 비트를 반영하도록 하드 코딩 된 32를 변경해야합니다 (또는를 사용하여 프로그래밍 방식으로 유도 Enum.GetUnderlyingType()
).
다음은 플래그 열거 형 안전 변환 방법입니다.
public static bool TryConvertToEnum<T>(this int instance, out T result)
where T: Enum
{
var enumType = typeof (T);
var success = Enum.IsDefined(enumType, instance);
if (success)
{
result = (T)Enum.ToObject(enumType, instance);
}
else
{
result = default(T);
}
return success;
}
Enum
대신 #로 제한하여 C # 7.3으로 개선 할 수 있습니다 struct
. 즉, 런타임 검사에 의존 할 필요가 없습니다.
문자열을 ENUM 또는 int를 ENUM 상수로 변환하려면 Enum.Parse 함수를 사용해야합니다. 다음은 실제로 문자열이 있고 int에 적용되는 YouTube 비디오 https://www.youtube.com/watch?v=4nhx4VwdRDk 입니다.
"red"는 문자열이고 "MyColors"는 색상 상수가있는 색상 ENUM입니다.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
약간 떨어져 원래의 질문에서 받고,하지만 난 찾을 스택 오버플로 질문에 대한 답변 열거에서 가져 오기 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 상수를 저장하면 꽤 깔끔한 솔루션처럼 보입니다.
위의 Tawani 유틸리티 클래스와 같은 제네릭을 사용하여 dot.NET 4.0에서 부분 일치하는 정수 또는 문자열을 대상 열거 형으로 구문 분석합니다. 불완전 할 수있는 명령 줄 스위치 변수를 변환하는 데 사용하고 있습니다. 열거 형은 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 ()에서 명시 적으로 변환하지 않습니다.
문자열에서 : (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;
}
}
다음은 Enum에서 Description을 가져 오는 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>();
이 열거 확장의 일부를 어디에서 얻었는지 더 이상 알지 못하지만 stackoverflow에서 온 것입니다. 죄송합니다! 그러나 나는 이것을 가지고 플래그로 열거 형을 위해 그것을 수정했다. 플래그가있는 열거 형의 경우 다음과 같이했습니다.
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;
좀 더 견고하게하려면 어떤 유형의 일치 완화를 빌드해야합니다.
public static T ToEnum<T>(dynamic value)
{
if (value == null)
{
// default value of an enum is the object that corresponds to
// the default value of its underlying type
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
}
else if (value is string name)
{
return (T)Enum.Parse(typeof(T), name);
}
return (T)Enum.ToObject(typeof(T),
Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}
테스트 사례
[Flags]
public enum A : uint
{
None = 0,
X = 1 < 0,
Y = 1 < 1
}
static void Main(string[] args)
{
var value = EnumHelper.ToEnum<A>(7m);
var x = value.HasFlag(A.X); // true
var y = value.HasFlag(A.Y); // true
var value2 = EnumHelper.ToEnum<A>("X");
var value3 = EnumHelper.ToEnum<A>(null);
Console.ReadKey();
}
주조 여러 가지 방법 과에서 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);
}
}
입력 데이터를 사용자가 원하는 enum 으로 변환하는 데 도움이됩니다 . 기본적으로 int 와 같은 열거 형이 있다고 가정하십시오 . 열거 형의 처음에 기본값을 추가 하십시오. 입력 값과 일치하는 항목이 없을 때 헬퍼 방법에 사용됩니다.
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;
}
}
주의 : 열거가 기본으로하기 때문에 나는 여기, INT에 값을 구문 분석하려고 INT 당신이이 같은 열거 정의하면 바이트 유형입니다.
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);
내 영어 죄송합니다
다음 캐스트 확장 방법이다 Int32
에 Enum
.
값이 최대 값보다 높은 경우에도 비트 단위 플래그를 사용합니다. 예를 들어 가능성이 1 , 2 및 4 인 열거 형이 있지만 int가 9 인 경우 8이 없으면 1 로 이해합니다 . 이를 통해 코드 업데이트보다 먼저 데이터를 업데이트 할 수 있습니다.
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);
}
int를 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));
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace SamplePrograme
{
public class Program
{
public enum Suit : int
{
Spades = 0,
Hearts = 1,
Clubs = 2,
Diamonds = 3
}
public static void Main(string[] args)
{
//from string
Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));
//from int
Console.WriteLine((Suit)1);
//From number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
}
}
}
당신은 아래처럼 좋아합니다 :
int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;
올바른 값만 캐스트하고 그렇지 않으면 예외를 던질 수 있습니다.
int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
TargetEnum target = (TargetEnum)intToCast ;
}
else
{
// Throw your exception.
}
IsDefined를 사용하는 것은 캐스팅하는 것보다 비용이 많이 들고 훨씬 더 많은 비용이 소요되므로 사용 여부를 결정하는 구현에 따라 다릅니다.
확장 방법을 사용할 수 있습니다.
public static class Extensions
{
public static T ToEnum<T>(this string data) where T : struct
{
if (!Enum.TryParse(data, true, out T enumVariable))
{
if (Enum.IsDefined(typeof(T), enumVariable))
{
return enumVariable;
}
}
return default;
}
public static T ToEnum<T>(this int data) where T : struct
{
return (T)Enum.ToObject(typeof(T), data);
}
}
벨로우즈 코드처럼 사용
열거 형 :
public enum DaysOfWeeks
{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
}
사용법 :
string Monday = "Mon";
int Wednesday = 3;
var Mon = Monday.ToEnum<DaysOfWeeks>();
var Wed = Wednesday.ToEnum<DaysOfWeeks>();
YourEnum
동적이고 런타임에만 알려지면 어떻게해야Enum
합니까?