c# - 이유 - 유니티 public enum




C#에서 문자열을 열거 형으로 변환 (16)

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의 핵심 클래스를 어수선하게 만드는 것이 가장 좋습니다.


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
}

TryParse를 사용하는 매우 간단한 코드 :

var value = "Active";

StatusEnum status;
if (!Enum.TryParse<StatusEnum>(value, out status))
    status = StatusEnum.Unknown;

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

당신은 Enum.Parse 찾고 있습니다.

SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");

성능을 위해 이것은 도움이 될 수 있습니다.

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

우리는 완벽하게 유효한 입력을 가정 할 수 없었으며 @Keith의 대답 변형을 따라갔습니다.

public static TEnum ParseEnum<TEnum>(string value) where TEnum : struct
{
    TEnum tmp; 
    if (!Enum.TryParse<TEnum>(value, true, out tmp))
    {
        tmp = new TEnum();
    }
    return tmp;
}

이 샘플을 사용해보십시오 :

 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 유형으로 반환하십시오.


이제 확장 방법을 사용할 수 있습니다 :

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 버전)를 사용했습니다. 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


Enum.Parse 는 당신의 친구입니다 :

StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");

Enum.Parse() 의 성능은 리플렉션을 통해 구현되기 때문에 끔찍합니다. Enum.ToString 도 마찬가지입니다.

성능에 민감한 코드에서 문자열을 열거 형으로 변환해야하는 경우 가장 좋은 방법은 시작시 Dictionary<String,YourEnum> 을 만들어 변환을 수행하는 것입니다.


// str.ToEnum<EnumType>()
T static ToEnum<T>(this string str) 
{ 
    return (T) Enum.Parse(typeof(T), str);
}

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

public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){
if (string.IsNullOrEmpty(value))
    return defaultValue;

return Enum.Parse(typeof(TEnum), value, true);}

        <Extension()>
    Public Function ToEnum(Of TEnum)(ByVal value As String, ByVal defaultValue As TEnum) As TEnum
        If String.IsNullOrEmpty(value) Then
            Return defaultValue
        End If

        Return [Enum].Parse(GetType(TEnum), value, True)
    End Function




enums