[C#] C #에서 문자열을 열거 형으로 변환

C #에서 문자열을 열거 형 값으로 변환하는 가장 좋은 방법은 무엇입니까?

열거 형 값을 포함하는 HTML select 태그가 있습니다. 페이지가 게시되면 값 (문자열 형식)을 가져 와서 열거 형 값으로 변환하고 싶습니다.

이상적인 세상에서는 다음과 같이 할 수 있습니다.

StatusEnum MyStatus = StatusEnum.Parse("Active");

그러나 그것은 유효한 코드가 아닙니다.



답변

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


답변

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


답변

object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

따라서 분위기라는 열거 형이 있으면 다음과 같습니다.

   enum Mood
   {
      Angry,
      Happy,
      Sad
   }

   // ...
   Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true);
   Console.WriteLine("My mood is: {0}", m.ToString());


답변

주의 :

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