programing

문자열을 C#의 열거형으로 변환합니다.

easyjava 2023. 4. 19. 23:34
반응형

문자열을 C#의 열거형으로 변환합니다.

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

열거 값을 포함하는 HTML 선택 태그가 있습니다.페이지가 게시되면 값(문자열 형식)을 선택하여 대응하는 열거값으로 변환합니다.

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

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

유효한 코드가 아닙니다.

.NET Core 및 의 경우.NET Framework © 4.0에는 일반적인 해석 방법이 있습니다.

Enum.TryParse("Active", out StatusEnum myStatus);

에는 C 인라인 C#7도 됩니다.out되고 try-display, try-display, try-display는 초기화 및 됩니다.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(따라서 "num"을 보유하지 않음)1234.ToString().ToEnum(StatusEnum.None)유효하지만 말도 안 됩니다.)개발팀 전체가 확장 기능에 대해 잘 이해하지 못하는 한 특정 컨텍스트에서만 적용되는 추가 방법을 사용하여 Microsoft의 핵심 클래스를 복잡하게 만들지 않는 것이 좋습니다.

( )를 사용합니다.NET 4.0):

StatusEnum myStatus;
Enum.TryParse("Active", out myStatus);

C# 7.0 파라미터 타입의 인라인에 의해, 한층 더 심플화할 수 있습니다.

Enum.TryParse("Active", out StatusEnum myStatus);

「 」의 퍼포먼스는,Enum.Parse()이상적이지 않습니다.(동일하다Enum.ToString()(서양속담, 친구속담)

코드에서 Enums를 .Dictionary<String,YourEnum>이를 사용하여 변환을 수행합니다.

당신은 Enum을 찾고 있어요.해석.

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 값은 int int int int int int int 입니다.3그건 더 심해요.Enum.Parse() Enum.Parse()는 Enum을 사용합니다.

사용자가 의도하든 의도하지 않든 간에 이러한 행동을 촉발하는 결과를 경험하고 싶지 않습니다.

또한 다른 사람들이 언급했듯이 성능은 대규모 에넘(예: 가능한 값의 수에서 선형)에 적합하지 않습니다.

다음을 권장합니다.

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

어느 시점에서 일반 버전의 Parse가 추가되었습니다.해석할 필요가 없고 출력 변수를 생성하지 않고 결과를 인라인으로 만들고 싶기 때문에 이 방법이 더 바람직했습니다.

ColorEnum color = Enum.Parse<ColorEnum>("blue");

MS 문서: 해석

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

따라서 mood라는 이름의 열거형이 있다면 다음과 같습니다.

   enum Mood
   {
      Angry,
      Happy,
      Sad
   } 

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

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이 아닌 경우 Enum.TryParse는 실패하고 예외가 발생하며, 예외는 포착됩니다.

코드로 이 기능을 오랫동안 사용해 온 많은 장소에서는, 이 조작에 의해서 퍼포먼스가 저하된다고 하는 정보를 추가하는 것이 좋을지도 모릅니다.

우리는 완전히 유효한 입력을 가정할 수 없었고, @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;
}
// str.ToEnum<EnumType>()
T static ToEnum<T>(this string str) 
{ 
    return (T) Enum.Parse(typeof(T), str);
}

이것이 언제 추가되었는지 알 수 없지만 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;
    }

이 응답의 대부분은 확장 메서드를 호출할 때마다 항상 기본값인 열거값을 전달해야 합니다.이 방법을 사용하고 싶지 않은 경우 다음과 같이 구현할 수 있습니다.

 public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
 {
     if (string.IsNullOrWhiteSpace(value))
          return default(TEnum);

     return Enum.TryParse(value, true, out TEnum result) ? result : default(TEnum);

 }

디폴트 리터럴 사용(C# 7.1에서 사용 가능)

 public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue = default) where TEnum : struct
 {
       if (string.IsNullOrWhiteSpace(value))
            return defaultValue ;

       return Enum.TryParse(value, true, out TEnum result) ? result : defaultValue ;

 }

더 좋은 점은:

public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
{
      if (string.IsNullOrWhiteSpace(value))
           return default;

      return Enum.TryParse(value, true, out TEnum result) ? result : default;

}

try/catch를 사용하지 않고에서 TryParse() 메서드를 사용하지 않고 문자열을 TEnum으로 해석합니다.NET 4.5

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

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

var value = "Active";

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

퍼포먼스에 도움이 되는 것은, 다음과 같습니다.

    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];
    }
public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){
if (string.IsNullOrEmpty(value))
    return defaultValue;

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

속성 이름이 원하는 이름과 다른 경우(예: 언어 차이) 다음과 같이 수행할 수 있습니다.

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

여기서 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에서 개체 값을 가져온 후 개체 값을 특정 Enum 값으로 변경해야 합니다.Enum 값으로 캐스팅하려면 Convert를 사용합니다.[ Change Type ]를 선택합니다.다음 코드 스니펫을 확인하십시오.

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유형.

        <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

null 또는 empty일 때 기본값을 사용하고(예를 들어 config 파일에서 가져오고 값이 존재하지 않는 경우) 문자열 또는 번호가 열거값과 일치하지 않을 때 예외를 발생시키는 경우.단, Timo의 답변에 주의해 주십시오(https://stackoverflow.com/a/34267134/2454604)).

    public static T ParseEnum<T>(this string s, T defaultValue, bool ignoreCase = false) 
        where T : struct, IComparable, IConvertible, IFormattable//If C# >=7.3: struct, System.Enum 
    {
        if ((s?.Length ?? 0) == 0)
        {
            return defaultValue;
        }

        var valid = Enum.TryParse<T>(s, ignoreCase, out T res);

        if (!valid || !Enum.IsDefined(typeof(T), res))
        {
            throw new InvalidOperationException(
                $"'{s}' is not a valid value of enum '{typeof(T).FullName}'!");
        }
        return res;
    }

저는 이 방법을 사용하기 시작했습니다.성능은 괜찮은 것 같지만 약간의 보일러 플레이트 코드 설정이 필요합니다.

public enum StatusType {
    Success,
    Pending,
    Rejected
}

static class StatusTypeMethods {

    public static StatusType GetEnum(string type) {
        switch (type) {
            case nameof(StatusType.Success): return StatusType.Success;
            case nameof(StatusType.Pending): return StatusType.Pending;
            case nameof(StatusType.Rejected): return StatusType.Rejected;
            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        };
    }
}

나중에 다음과 같이 사용할 수 있습니다.

StatusType = StatusType.GetEnum("Success");

먼저 열거형을 다음과 같이 꾸밀 필요가 있습니다.

    public enum Store : short
{
    [Description("Rio Big Store")]
    Rio = 1
}

.net 5에서는 다음 확장 메서드를 만듭니다.

//The class also needs to be static, ok?
public static string GetDescription(this System.Enum enumValue)
    {
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0) return attributes[0].Description;
        else return enumValue.ToString();
    }

이제 모든 Enums에서 사용할 확장 메서드가 있습니다.

다음과 같이 합니다.

var Desc = Store.Rio.GetDescription(); //Store is your Enum

언급URL : https://stackoverflow.com/questions/16100/convert-a-string-to-an-enum-in-c-sharp

반응형