답변:
.NET Core 및 .NET> 4 에는 일반적인 구문 분석 방법이 있습니다 .
Enum.TryParse("Active", out StatusEnum myStatus);
여기에는 C # 7의 새로운 인라인 out
변수 도 포함 되므로 try-parse를 수행하고 명시 적 열거 형 유형으로 변환하고 myStatus
변수를 초기화하고 채 웁니다 .
C # 7 및 최신 .NET에 액세스 할 수있는 것이 가장 좋습니다.
.NET에서는 다소 추악합니다 (4 이상).
StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);
나는 이것을 다음과 같이 단순화하는 경향이있다 :
public static T ParseEnum<T>(string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
그런 다음 할 수 있습니다 :
StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");
의견에서 제안 된 옵션 중 하나는 확장을 추가하는 것입니다.
public static T ToEnum<T>(this string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();
마지막으로 문자열을 구문 분석 할 수없는 경우 사용할 기본 열거 형을 가질 수 있습니다.
public static T ToEnum<T>(this string value, T defaultValue)
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
T result;
return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}
이것은 이것을 전화로 만듭니다 :
StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);
그러나 string
(네임 스페이스 제어없이) 이와 같은 확장 메소드를 추가 string
하면 열거 형을 보유하는지 여부 에 관계없이 모든 인스턴스에 표시됩니다 ( 1234.ToString().ToEnum(StatusEnum.None)
유효하지만 무의미합니다). 전체 개발 팀이 확장 기능에 대해 잘 이해하지 않는 한 매우 구체적인 상황에만 적용되는 추가 메서드를 사용하여 Microsoft의 핵심 클래스를 어수선하게 만드는 것이 가장 좋습니다.
사용 Enum.TryParse<T>(String, T)
(≥ .NET 4.0) :
StatusEnum myStatus;
Enum.TryParse("Active", out myStatus);
C # 7.0의 매개 변수 유형 인라이닝을 사용 하면 훨씬 간단해질 수 있습니다 .
Enum.TryParse("Active", out StatusEnum myStatus);
Parse
변환 오류 (값이 null
비어 있거나 해당 열거 상수가 없음)에 대한 설명 예외가 발생합니다.이 값은 TryParse
부울 반환 값 (구체적인 오류를 억제 함) 보다 낫습니다
var result = Enum.TryParse<System.DayOfWeek>("55", out var parsedEnum);
Enum.Parse()
리플렉션을 통해 구현되므로 성능 이 끔찍합니다. (의 Enum.ToString
반대도 마찬가지입니다 .)
성능에 민감한 코드에서 문자열을 열거 형으로 변환해야하는 경우 가장 좋은 방법은 Dictionary<String,YourEnum>
시작시 생성하고 이를 사용하여 변환하는 것입니다.
당신은 Enum.Parse 찾고 있습니다.
SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
이제 확장 방법을 사용할 수 있습니다 :
public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
return (T) Enum.Parse(typeof (T), value, ignoreCase);
}
그리고 당신은 아래 코드로 그들을 호출 할 수 있습니다 (여기서는 FilterType
열거 형입니다) :
FilterType filterType = type.ToEnum<FilterType>();
주의 :
enum Example
{
One = 1,
Two = 2,
Three = 3
}
Enum.(Try)Parse()
쉼표로 구분 된 여러 인수를 허용하고 이진수 'or'와 결합합니다|
. 당신은 이것을 비활성화 할 수 없으며 내 의견으로는 거의 그것을 원하지 않습니다.
var x = Enum.Parse("One,Two"); // x is now Three
Three
정의되지 않은 경우에도 x
여전히 int value를 얻습니다 3
. 더 나쁘다 : Enum.Parse ()는 열거 형에 대해 정의되지 않은 값을 줄 수 있습니다!
기꺼이 또는 의지하지 않고 사용자의 결과를 경험하고 싶지 않아이 행동을 유발하고 싶습니다.
또한 다른 사람들이 언급했듯이 성능은 큰 열거 형에 이상적입니다. 즉 가능한 값 수에 선형 적입니다.
나는 다음을 제안한다.
public static bool TryParse<T>(string value, out T result)
where T : struct
{
var cacheKey = "Enum_" + typeof(T).FullName;
// [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily.
// [Implementation off-topic.]
var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary<T>, EnumCacheExpiration);
return enumDictionary.TryGetValue(value.Trim(), out result);
}
private static Dictionary<string, T> CreateEnumDictionary<T>()
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase);
}
Enum.(Try)Parse accepts multiple, comma-separated arguments, and combines them with binary 'or'
. 열거 형 값을 2의 거듭 제곱으로 설정할 수 있으며 여러 부울 플래그를 구문 분석하는 매우 쉬운 방법이 있습니다. "UseSSL, NoRetries, Sync". 실제로 그것은 아마도 그것이 설계된 것입니다.
Enum.Parse 는 당신의 친구입니다 :
StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
예외를 피하기 위해 허용 된 답변을 기본값으로 확장 할 수 있습니다.
public static T ParseEnum<T>(string value, T defaultValue) where T : struct
{
try
{
T enumValue;
if (!Enum.TryParse(value, true, out enumValue))
{
return defaultValue;
}
return enumValue;
}
catch (Exception)
{
return defaultValue;
}
}
그런 다음 다음과 같이 호출합니다.
StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);
기본값이 열거 형이 아닌 경우 Enum.TryParse가 실패하고 포착 된 예외가 발생합니다.
수년간 코드에서이 함수를 여러 곳에서 사용한 후에는이 작업에 성능이 필요한 정보를 추가하는 것이 좋습니다!
defaultValue
메소드 반환 유형은 모두 유형 T
입니다. 유형이 다른 경우 컴파일 시간 오류가 나타납니다. " 'ConsoleApp1.Size'에서 'ConsoleApp1.Color'로 변환 할 수 없습니다."
try / catch 및 .NET 4.5의 TryParse () 메서드없이 문자열을 TEnum으로 구문 분석합니다.
/// <summary>
/// Parses string to TEnum without try/catch and .NET 4.5 TryParse()
/// </summary>
public static bool TryParseToEnum<TEnum>(string probablyEnumAsString_, out TEnum enumValue_) where TEnum : struct
{
enumValue_ = (TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0);
if(!Enum.IsDefined(typeof(TEnum), probablyEnumAsString_))
return false;
enumValue_ = (TEnum) Enum.Parse(typeof(TEnum), probablyEnumAsString_);
return true;
}
나는 확장 방법 솔루션을 좋아한다 ..
namespace System
{
public static class StringExtensions
{
public static bool TryParseAsEnum<T>(this string value, out T output) where T : struct
{
T result;
var isEnum = Enum.TryParse(value, out result);
output = isEnum ? result : default(T);
return isEnum;
}
}
}
다음은 테스트로 구현 한 것입니다.
using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using static System.Console;
private enum Countries
{
NorthAmerica,
Europe,
Rusia,
Brasil,
China,
Asia,
Australia
}
[TestMethod]
public void StringExtensions_On_TryParseAsEnum()
{
var countryName = "Rusia";
Countries country;
var isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsTrue(isCountry);
AreEqual(Countries.Rusia, country);
countryName = "Don't exist";
isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsFalse(isCountry);
AreEqual(Countries.NorthAmerica, country); // the 1rst one in the enumeration
}
public static T ParseEnum<T>(string value) //function declaration
{
return (T) Enum.Parse(typeof(T), value);
}
Importance imp = EnumUtil.ParseEnum<Importance>("Active"); //function call
==================== 완전한 프로그램 ====================
using System;
class Program
{
enum PetType
{
None,
Cat = 1,
Dog = 2
}
static void Main()
{
// Possible user input:
string value = "Dog";
// Try to convert the string to an enum:
PetType pet = (PetType)Enum.Parse(typeof(PetType), value);
// See if the conversion succeeded:
if (pet == PetType.Dog)
{
Console.WriteLine("Equals dog.");
}
}
}
-------------
Output
Equals dog.
클래스 (구문 분석 및 성능 향상과 함께 강력한 형식의 Enum 버전)를 사용했습니다. GitHub에서 찾았으며 .NET 3.5에서도 작동합니다. 사전을 버퍼링하기 때문에 약간의 메모리 오버 헤드가 있습니다.
StatusEnum MyStatus = Enum<StatusEnum>.Parse("Active");
블로그 게시물은 Enums – NET 3.5의 향상된 구문, 향상된 성능 및 TryParse입니다 .
그리고 코드 : https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/System/EnumT.cs
성능 향상을 위해 다음이 도움이 될 수 있습니다.
private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
public static T ToEnum<T>(this string value, T defaultValue)
{
var t = typeof(T);
Dictionary<string, object> dic;
if (!dicEnum.ContainsKey(t))
{
dic = new Dictionary<string, object>();
dicEnum.Add(t, dic);
foreach (var en in Enum.GetValues(t))
dic.Add(en.ToString(), en);
}
else
dic = dicEnum[t];
if (!dic.ContainsKey(value))
return defaultValue;
else
return (T)dic[value];
}
EnumMember 값을 가진 enum 값이있는 경우는 고려되지 않았습니다. 그래서 우리는 간다 :
using System.Runtime.Serialization;
public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue) where TEnum : struct
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
TEnum result;
var enumType = typeof(TEnum);
foreach (var enumName in Enum.GetNames(enumType))
{
var fieldInfo = enumType.GetField(enumName);
var enumMemberAttribute = ((EnumMemberAttribute[]) fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true)).FirstOrDefault();
if (enumMemberAttribute?.Value == value)
{
return Enum.TryParse(enumName, true, out result) ? result : defaultValue;
}
}
return Enum.TryParse(value, true, out result) ? result : defaultValue;
}
그리고 그 열거의 예 :
public enum OracleInstanceStatus
{
Unknown = -1,
Started = 1,
Mounted = 2,
Open = 3,
[EnumMember(Value = "OPEN MIGRATE")]
OpenMigrate = 4
}
Enum에서 개체 값을 가져 오려면 Enum.Parse를 사용해야합니다. 그런 다음 개체 값을 특정 열거 형 값으로 변경해야합니다. 열거 형 값으로 캐스트는 Convert.ChangeType을 사용하여 수행 할 수 있습니다. 다음 코드 스 니펫을 살펴보십시오.
public T ConvertStringValueToEnum<T>(string valueToParse){
return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T));
}
이 샘플을 사용해보십시오 :
public static T GetEnum<T>(string model)
{
var newModel = GetStringForEnum(model);
if (!Enum.IsDefined(typeof(T), newModel))
{
return (T)Enum.Parse(typeof(T), "None", true);
}
return (T)Enum.Parse(typeof(T), newModel.Result, true);
}
private static Task<string> GetStringForEnum(string model)
{
return Task.Run(() =>
{
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
var nonAlphanumericData = rgx.Matches(model);
if (nonAlphanumericData.Count < 1)
{
return model;
}
foreach (var item in nonAlphanumericData)
{
model = model.Replace((string)item, "");
}
return model;
});
}
이 샘플에서는 모든 문자열을 보내고을 설정할 수 있습니다 Enum
. 귀하의 경우 Enum
한 데이터는 당신이 원하는 것을, 당신으로 그 반환 Enum
유형입니다.
newModel
각 줄을 덮어 쓰므 로 대시가 포함되어 있으면 바뀌지 않습니다. 또한 문자열에 아무것도 포함되어 있는지 확인할 필요가 없습니다 Replace
. 어쨌든 전화 할 수 있습니다 .var newModel = model.Replace("-", "").Replace(" ", "");
이것이 언제 추가되었는지 확실하지 않지만 Enum 클래스에는 이제
Parse<TEnum>(stringValue)
문제의 예와 같이 사용됩니다.
var MyStatus = Enum.Parse<StatusEnum >("Active")
또는 다음을 통해 케이스를 무시합니다.
var MyStatus = Enum.Parse<StatusEnum >("active", true)
이것이 사용하는 디 컴파일 된 메소드는 다음과 같습니다.
[NullableContext(0)]
public static TEnum Parse<TEnum>([Nullable(1)] string value) where TEnum : struct
{
return Enum.Parse<TEnum>(value, false);
}
[NullableContext(0)]
public static TEnum Parse<TEnum>([Nullable(1)] string value, bool ignoreCase) where TEnum : struct
{
TEnum result;
Enum.TryParse<TEnum>(value, ignoreCase, true, out result);
return result;
}
속성 이름이 호출하려는 것과 다른 경우 (예 : 언어 차이) 다음과 같이 할 수 있습니다.
MyType.cs
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public enum MyType
{
[EnumMember(Value = "person")]
Person,
[EnumMember(Value = "annan_deltagare")]
OtherPerson,
[EnumMember(Value = "regel")]
Rule,
}
EnumExtensions.cs
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public static class EnumExtensions
{
public static TEnum ToEnum<TEnum>(this string value) where TEnum : Enum
{
var jsonString = $"'{value.ToLower()}'";
return JsonConvert.DeserializeObject<TEnum>(jsonString, new StringEnumConverter());
}
public static bool EqualsTo<TEnum>(this string strA, TEnum enumB) where TEnum : Enum
{
TEnum enumA;
try
{
enumA = strA.ToEnum<TEnum>();
}
catch
{
return false;
}
return enumA.Equals(enumB);
}
}
Program.cs
public class Program
{
static public void Main(String[] args)
{
var myString = "annan_deltagare";
var myType = myString.ToEnum<MyType>();
var isEqual = myString.EqualsTo(MyType.OtherPerson);
//Output: true
}
}