type parse from enum convert c# string enums

parse - string to enum c#



¿Cómo debo convertir una cadena a una enumeración en C#? (20)

¿Cuál es la mejor manera de convertir una cadena a un valor de enumeración en C #?

Tengo una etiqueta de selección HTML que contiene los valores de una enumeración. Cuando se publique la página, quiero recoger el valor (que estará en forma de cadena) y convertirlo al valor de enumeración.

En un mundo ideal, podría hacer algo como esto:

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

Pero eso no es un código válido.


Analiza la cadena a TEnum sin try / catch y sin el método TryParse () desde .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; }


Código super simple usando TryParse:

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


En .NET Core y .NET> 4 hay un método de análisis genérico :

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

Esto también incluye las nuevas variables inline out C # 7, por lo que hace el try-parse, la conversión al tipo de enumeración explícito e inicializa + llena la variable myStatus .

Si tiene acceso a C # 7 y el último .NET, esta es la mejor manera.

Respuesta original

En .NET es bastante feo (hasta 4 o más):

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

Tiendo a simplificar esto con:

public static T ParseEnum<T>(string value) { return (T) Enum.Parse(typeof(T), value, true); }

Entonces puedo hacer:

StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");

Una opción sugerida en los comentarios es agregar una extensión, que es lo suficientemente simple:

public static T ToEnum<T>(this string value) { return (T) Enum.Parse(typeof(T), value, true); } StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();

Finalmente, es posible que desee tener una enumeración predeterminada para usar si la cadena no se puede analizar:

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

Lo que hace de esta la llamada:

StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);

Sin embargo, tendría cuidado al agregar un método de extensión como este a la string ya que (sin control de espacio de nombres) aparecerá en todas las instancias de la string ya sea que tengan una enumeración o no (por 1234.ToString().ToEnum(StatusEnum.None) tanto, 1234.ToString().ToEnum(StatusEnum.None) ser válido pero sin sentido). A menudo es mejor evitar saturar las clases principales de Microsoft con métodos adicionales que solo se aplican en contextos muy específicos, a menos que todo su equipo de desarrollo tenga una muy buena comprensión de lo que hacen esas extensiones.


Encontré que aquí el caso con valores de enumeración que tienen valor EnumMember no fue considerado. Así que, aquí vamos:

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

Y ejemplo de esa enumeración:

public enum OracleInstanceStatus { Unknown = -1, Started = 1, Mounted = 2, Open = 3, [EnumMember(Value = "OPEN MIGRATE")] OpenMigrate = 4 }


Estás buscando Enum.Parse .

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


Me gusta la solución del método de extensión.

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

Aquí abajo mi implementación con pruebas.

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 }


No pudimos asumir una entrada perfectamente válida, y seguimos con esta variación de la respuesta de @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; }


Para el rendimiento, esto podría ayudar:

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


Prueba esta muestra:

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

En esta muestra puedes enviar cada cadena y configurar tu Enum . Si su Enum tenía los datos que deseaba, devuélvalos como su tipo de Enum .


Puede extender la respuesta aceptada con un valor predeterminado para evitar excepciones:

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

Entonces lo llamas como:

StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);


Puede utilizar métodos de extensión ahora:

public static T ToEnum<T>(this string value, bool ignoreCase = true) { return (T) Enum.Parse(typeof (T), value, ignoreCase); }

Y puede llamarlos por el siguiente código (aquí, FilterType es un tipo de enumeración):

FilterType filterType = type.ToEnum<FilterType>();


Tenga en cuenta que el rendimiento de Enum.Parse () es horrible, porque se implementa a través de la reflexión. (Lo mismo se aplica a Enum.ToString, que va a la inversa).

Si necesita convertir cadenas a Enums en código sensible al rendimiento, lo mejor es crear un Dictionary<String,YourEnum> al inicio y usarlo para hacer sus conversiones.


Tienes que usar Enum.Parse para obtener el valor del objeto de Enum, después de eso tienes que cambiar el valor del objeto a un valor de enumeración específico. La conversión al valor enum se puede hacer utilizando Convert.ChangeType. Por favor, eche un vistazo en el siguiente fragmento de código

public T ConvertStringValueToEnum<T>(string valueToParse){ return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T)); }




Enum.Parse es tu amigo:

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


TENER CUIDADO:

enum Example { One = 1, Two = 2, Three = 3 }

Enum.(Try)Parse() acepta varios argumentos separados por comas y los combina con el binario ''o'' | . No puedes deshabilitar esto y, en mi opinión, casi nunca lo quieres.

var x = Enum.Parse("One,Two"); // x is now Three

Incluso si Three no estaba definido, x todavía obtendría valor int 3 . Eso es aún peor: ¡Enum.Parse () puede darle un valor que ni siquiera está definido para la enumeración!

No quisiera experimentar las consecuencias de los usuarios, voluntaria o involuntariamente, desencadenando este comportamiento.

Además, como lo mencionaron otros, el rendimiento es inferior al ideal para grandes enumeraciones, es decir, lineal en el número de valores posibles.

Sugiero lo siguiente:

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


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

Así que si tuvieras un estado de ánimo llamado enum se vería así:

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


public static T ParseEnum<T>(string value) //function declaration { return (T) Enum.Parse(typeof(T), value); } Importance imp = EnumUtil.ParseEnum<Importance>("Active"); //function call

==================== Un programa completo ====================

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.