clase - enum string c#
Crear método genérico que restringe T a un Enum (20)
C # ≥ 7.3
Comenzando con C # 7.3 (disponible con Visual Studio 2017 ≥ v15.7), este código ahora es completamente válido:
public static TEnum Parse<TEnum>(string value)
where TEnum : struct, Enum { ... }
C # ≤ 7.2
Puede hacer que un compilador real aplique una restricción de enumeración al abusar de la herencia de la restricción. El siguiente código especifica las restricciones de class
y struct
al mismo tiempo:
public abstract class EnumClassUtils<TClass>
where TClass : class
{
public static TEnum Parse<TEnum>(string value)
where TEnum : struct, TClass
{
return (TEnum) Enum.Parse(typeof(TEnum), value);
}
}
public class EnumUtils : EnumClassUtils<Enum>
{
}
Uso:
EnumUtils.Parse<SomeEnum>("value");
Nota: esto se establece específicamente en la especificación de lenguaje C # 5.0:
Si el parámetro de tipo S depende del parámetro de tipo T, entonces: [...] Es válido que S tenga la restricción de tipo de valor y que T tenga la restricción de tipo de referencia. Efectivamente, esto limita T a los tipos System.Object, System.ValueType, System.Enum y cualquier tipo de interfaz.
Estoy construyendo una función para extender el concepto Enum.Parse
que
- Permite que se analice un valor predeterminado en caso de que no se encuentre un valor Enum
- Es insensible a mayúsculas
Así que escribí lo siguiente:
public static T GetEnumFromString<T>(string value, T defaultValue) where T : Enum
{
if (string.IsNullOrEmpty(value)) return defaultValue;
foreach (T item in Enum.GetValues(typeof(T)))
{
if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
}
return defaultValue;
}
Estoy obteniendo una restricción de error no puede ser una clase especial System.Enum
.
Justo lo suficiente, pero hay una solución para permitir un Enum Genérico, o voy a tener que imitar la función Parse
y pasar un tipo como atributo, lo que obliga al requisito del boxeo feo a su código.
EDITAR Todas las sugerencias a continuación han sido muy apreciadas, gracias.
Se ha decidido por (he dejado el bucle para mantener la insensibilidad a las mayúsculas y minúsculas). Estoy usando esto al analizar XML.
public static class EnumUtils
{
public static T ParseEnum<T>(string value, T defaultValue) where T : struct, IConvertible
{
if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
if (string.IsNullOrEmpty(value)) return defaultValue;
foreach (T item in Enum.GetValues(typeof(T)))
{
if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
}
return defaultValue;
}
}
EDITAR: (16 de febrero de 2015) Julien Lebosquain ha publicado recientemente una solución genérica de tipo seguro aplicada por el compilador en MSIL o F # a continuación, que vale la pena ver, y un voto positivo. Eliminaré esta edición si la solución burbujea más arriba en la página.
¡Esta característica finalmente es compatible con C # 7.3!
El siguiente fragmento de código (de las muestras de dotnet ) demuestra su uso:
public static Dictionary<int, string> EnumNamedValues<T>() where T : System.Enum
{
var result = new Dictionary<int, string>();
var values = Enum.GetValues(typeof(T));
foreach (int item in values)
result.Add(item, Enum.GetName(typeof(T), item));
return result;
}
Asegúrese de configurar su versión de idioma en su proyecto de C # a la versión 7.3.
Respuesta original a continuación:
Llego tarde al juego, pero lo tomé como un desafío para ver cómo se podía hacer. No es posible en C # (o VB.NET, pero desplácese hacia abajo para F #), pero es posible en MSIL. Yo escribí esta pequeña ... cosa
// license: http://www.apache.org/licenses/LICENSE-2.0.html
.assembly MyThing{}
.class public abstract sealed MyThing.Thing
extends [mscorlib]System.Object
{
.method public static !!T GetEnumFromString<valuetype .ctor ([mscorlib]System.Enum) T>(string strValue,
!!T defaultValue) cil managed
{
.maxstack 2
.locals init ([0] !!T temp,
[1] !!T return_value,
[2] class [mscorlib]System.Collections.IEnumerator enumerator,
[3] class [mscorlib]System.IDisposable disposer)
// if(string.IsNullOrEmpty(strValue)) return defaultValue;
ldarg strValue
call bool [mscorlib]System.String::IsNullOrEmpty(string)
brfalse.s HASVALUE
br RETURNDEF // return default it empty
// foreach (T item in Enum.GetValues(typeof(T)))
HASVALUE:
// Enum.GetValues.GetEnumerator()
ldtoken !!T
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
call class [mscorlib]System.Array [mscorlib]System.Enum::GetValues(class [mscorlib]System.Type)
callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Array::GetEnumerator()
stloc enumerator
.try
{
CONDITION:
ldloc enumerator
callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
brfalse.s LEAVE
STATEMENTS:
// T item = (T)Enumerator.Current
ldloc enumerator
callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
unbox.any !!T
stloc temp
ldloca.s temp
constrained. !!T
// if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
callvirt instance string [mscorlib]System.Object::ToString()
callvirt instance string [mscorlib]System.String::ToLower()
ldarg strValue
callvirt instance string [mscorlib]System.String::Trim()
callvirt instance string [mscorlib]System.String::ToLower()
callvirt instance bool [mscorlib]System.String::Equals(string)
brfalse.s CONDITION
ldloc temp
stloc return_value
leave.s RETURNVAL
LEAVE:
leave.s RETURNDEF
}
finally
{
// ArrayList''s Enumerator may or may not inherit from IDisposable
ldloc enumerator
isinst [mscorlib]System.IDisposable
stloc.s disposer
ldloc.s disposer
ldnull
ceq
brtrue.s LEAVEFINALLY
ldloc.s disposer
callvirt instance void [mscorlib]System.IDisposable::Dispose()
LEAVEFINALLY:
endfinally
}
RETURNDEF:
ldarg defaultValue
stloc return_value
RETURNVAL:
ldloc return_value
ret
}
}
Lo que genera una función que se vería así, si fuera válida C #:
T GetEnumFromString<T>(string valueString, T defaultValue) where T : Enum
Luego con el siguiente código C #:
using MyThing;
// stuff...
private enum MyEnum { Yes, No, Okay }
static void Main(string[] args)
{
Thing.GetEnumFromString("No", MyEnum.Yes); // returns MyEnum.No
Thing.GetEnumFromString("Invalid", MyEnum.Okay); // returns MyEnum.Okay
Thing.GetEnumFromString("AnotherInvalid", 0); // compiler error, not an Enum
}
Desafortunadamente, esto significa tener esta parte de su código escrita en MSIL en lugar de C #, con el único beneficio adicional de que es capaz de restringir este método mediante System.Enum
. También es una especie de fastidio, porque se compila en un ensamblaje separado. Sin embargo, no significa que tenga que implementarlo de esa manera.
Al eliminar la línea .assembly MyThing{}
e invocar ilasm de la siguiente manera:
ilasm.exe /DLL /OUTPUT=MyThing.netmodule
obtienes un módulo de red en lugar de un ensamblaje.
Desafortunadamente, VS2010 (y anterior, obviamente) no admite la adición de referencias de netmodule, lo que significa que tendrías que dejarlo en 2 ensamblajes separados cuando estés depurando. La única manera de agregarlos como parte de su ensamblaje sería ejecutar csc.exe usted mismo usando el argumento de la línea de comando /addmodule:{files}
. No sería demasiado doloroso en un script de MSBuild. Por supuesto, si eres valiente o estúpido, puedes ejecutar csc tú mismo manualmente cada vez. Y, sin duda, se complica a medida que varios ensamblajes necesitan acceso a él.
Por lo tanto, se puede hacer en .Net. ¿Vale la pena el esfuerzo extra? Um, bueno, supongo que te dejaré decidir sobre eso.
F # Solución como alternativa
Crédito adicional: Resulta que es posible una restricción genérica en enum
en al menos otro lenguaje .NET además de MSIL: F #.
type MyThing =
static member GetEnumFromString<''T when ''T :> Enum> str defaultValue: ''T =
/// protect for null (only required in interop with C#)
let str = if isNull str then String.Empty else str
Enum.GetValues(typedefof<''T>)
|> Seq.cast<_>
|> Seq.tryFind(fun v -> String.Compare(v.ToString(), str.Trim(), true) = 0)
|> function Some x -> x | None -> defaultValue
Este es más fácil de mantener, ya que es un lenguaje conocido con soporte completo de Visual Studio IDE, pero aún necesita un proyecto separado en su solución para ello. Sin embargo, naturalmente produce una IL considerablemente diferente (el código es muy diferente) y se basa en la biblioteca FSharp.Core
, que, al igual que cualquier otra biblioteca externa, debe formar parte de su distribución.
Aquí le mostramos cómo puede usarlo (básicamente lo mismo que la solución MSIL), y para mostrar que falla correctamente en estructuras de otra manera:
// works, result is inferred to have type StringComparison
var result = MyThing.GetEnumFromString("OrdinalIgnoreCase", StringComparison.Ordinal);
// type restriction is recognized by C#, this fails at compile time
var result = MyThing.GetEnumFromString("OrdinalIgnoreCase", 42);
Como se indica en otras respuestas antes; Si bien esto no se puede expresar en código fuente, en realidad se puede hacer en el nivel de IL. La answer @Christopher Currens muestra cómo la IL hace eso.
Con el Fody de ExtraConstraints.Fody hay una manera muy simple, completa con herramientas de construcción, para lograr esto. Solo agregue sus paquetes nuget ( Fody
, ExtraConstraints.Fody
) a su proyecto y agregue las restricciones de la siguiente manera (Extracto del archivo Léame de ExtraConstraints):
public void MethodWithEnumConstraint<[EnumConstraint] T>() {...}
public void MethodWithTypeEnumConstraint<[EnumConstraint(typeof(ConsoleColor))] T>() {...}
y Fody agregará la IL necesaria para que la restricción esté presente. También tenga en cuenta la característica adicional de los delegados de restricción:
public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
{...}
public void MethodWithTypeDelegateConstraint<[DelegateConstraint(typeof(Func<int>))] T> ()
{...}
Con respecto a Enums, también puede tomar nota de los Enums.NET altamente interesantes .
Creé un método de extensión to get integer value from enum
Observe la implementación del método.
public static int ToInt<T>(this T soure) where T : IConvertible//enum
{
if (typeof(T).IsEnum)
{
return (int) (IConvertible)soure;// the tricky part
}
//else
// throw new ArgumentException("T must be an enumerated type");
return soure.ToInt32(CultureInfo.CurrentCulture);
}
esto es uso
MemberStatusEnum.Activated.ToInt()// using extension Method
(int) MemberStatusEnum.Activated //the ordinary way
Curiosamente, al parecer esto es posible en otros idiomas (Managed C ++, IL directamente).
Citar:
... Ambas restricciones producen realmente una IL válida y también pueden ser consumidas por C # si se escriben en otro idioma (puede declarar esas restricciones en C ++ administrado o en IL).
Quién sabe
Dado que Enum
Type implementa IConvertible
interfaz IConvertible
, una mejor implementación debería ser algo como esto:
public T GetEnumFromString<T>(string value) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
//...
}
Esto todavía permitirá pasar tipos de valor implementando IConvertible
. Sin embargo, las posibilidades son raras.
Espero que esto sea útil:
public static TValue ParseEnum<TValue>(string value, TValue defaultValue)
where TValue : struct // enum
{
try
{
if (String.IsNullOrEmpty(value))
return defaultValue;
return (TValue)Enum.Parse(typeof (TValue), value);
}
catch(Exception ex)
{
return defaultValue;
}
}
Esta es mi opinión. Combinado a partir de las respuestas y MSDN.
public static TEnum ParseToEnum<TEnum>(this string text) where TEnum : struct, IConvertible, IComparable, IFormattable
{
if (string.IsNullOrEmpty(text) || !typeof(TEnum).IsEnum)
throw new ArgumentException("TEnum must be an Enum type");
try
{
var enumValue = (TEnum)Enum.Parse(typeof(TEnum), text.Trim(), true);
return enumValue;
}
catch (Exception)
{
throw new ArgumentException(string.Format("{0} is not a member of the {1} enumeration.", text, typeof(TEnum).Name));
}
}
He encapsulado la solución de Vivek en una clase de utilidad que puede reutilizar. Tenga en cuenta que aún debe definir restricciones de tipo "donde T: struct, IConvertible" en su tipo.
using System;
internal static class EnumEnforcer
{
/// <summary>
/// Makes sure that generic input parameter is of an enumerated type.
/// </summary>
/// <typeparam name="T">Type that should be checked.</typeparam>
/// <param name="typeParameterName">Name of the type parameter.</param>
/// <param name="methodName">Name of the method which accepted the parameter.</param>
public static void EnforceIsEnum<T>(string typeParameterName, string methodName)
where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
string message = string.Format(
"Generic parameter {0} in {1} method forces an enumerated type. Make sure your type parameter {0} is an enum.",
typeParameterName,
methodName);
throw new ArgumentException(message);
}
}
/// <summary>
/// Makes sure that generic input parameter is of an enumerated type.
/// </summary>
/// <typeparam name="T">Type that should be checked.</typeparam>
/// <param name="typeParameterName">Name of the type parameter.</param>
/// <param name="methodName">Name of the method which accepted the parameter.</param>
/// <param name="inputParameterName">Name of the input parameter of this page.</param>
public static void EnforceIsEnum<T>(string typeParameterName, string methodName, string inputParameterName)
where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
string message = string.Format(
"Generic parameter {0} in {1} method forces an enumerated type. Make sure your input parameter {2} is of correct type.",
typeParameterName,
methodName,
inputParameterName);
throw new ArgumentException(message);
}
}
/// <summary>
/// Makes sure that generic input parameter is of an enumerated type.
/// </summary>
/// <typeparam name="T">Type that should be checked.</typeparam>
/// <param name="exceptionMessage">Message to show in case T is not an enum.</param>
public static void EnforceIsEnum<T>(string exceptionMessage)
where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException(exceptionMessage);
}
}
}
Intenté mejorar un poco el código:
public T LoadEnum<T>(string value, T defaultValue = default(T)) where T : struct, IComparable, IFormattable, IConvertible
{
if (Enum.IsDefined(typeof(T), value))
{
return (T)Enum.Parse(typeof(T), value, true);
}
return defaultValue;
}
Las respuestas existentes son verdaderas a partir de C # <= 7.2. Sin embargo, hay una solicitud de función de lenguaje C # (vinculada a una corefx función corefx ) para permitir lo siguiente;
public class MyGeneric<TEnum> where TEnum : System.Enum
{ }
Al momento de escribir, la característica es "En discusión" en las Reuniones de Desarrollo del Lenguaje.
EDITAR
Según la información de nawfal , esto se está introduciendo en C # 7.3 .
Me encantó la solución de Christopher Currens usando IL, pero para aquellos que no quieren lidiar con el complicado negocio de incluir MSIL en su proceso de compilación, escribí una función similar en C #.
Sin embargo, tenga en cuenta que no puede usar la restricción genérica como where T : Enum
porque Enum es un tipo especial. Por lo tanto, tengo que comprobar si el tipo genérico dado es realmente enumeración.
Mi función es:
public static T GetEnumFromString<T>(string strValue, T defaultValue)
{
// Check if it realy enum at runtime
if (!typeof(T).IsEnum)
throw new ArgumentException("Method GetEnumFromString can be used with enums only");
if (!string.IsNullOrEmpty(strValue))
{
IEnumerator enumerator = Enum.GetValues(typeof(T)).GetEnumerator();
while (enumerator.MoveNext())
{
T temp = (T)enumerator.Current;
if (temp.ToString().ToLower().Equals(strValue.Trim().ToLower()))
return temp;
}
}
return defaultValue;
}
Modifiqué la muestra por dimarzionista. Esta versión solo funcionará con Enums y no permitirá que se realicen las estructuras.
public static T ParseEnum<T>(string enumString)
where T : struct // enum
{
if (String.IsNullOrEmpty(enumString) || !typeof(T).IsEnum)
throw new Exception("Type given must be an Enum");
try
{
return (T)Enum.Parse(typeof(T), enumString, true);
}
catch (Exception ex)
{
return default(T);
}
}
Puede definir un constructor estático para la clase que verificará que el tipo T sea una enumeración y arroje una excepción si no lo es. Este es el método mencionado por Jeffery Richter en su libro CLR a través de C #.
internal sealed class GenericTypeThatRequiresAnEnum<T> {
static GenericTypeThatRequiresAnEnum() {
if (!typeof(T).IsEnum) {
throw new ArgumentException("T must be an enumerated type");
}
}
}
Luego, en el método de análisis, puede usar Enum.Parse (typeof (T), input, true) para convertir de cadena a la enumeración. El último parámetro verdadero es para ignorar el caso de la entrada.
Siempre me ha gustado esto (se podría modificar según corresponda):
public static IEnumerable<TEnum> GetEnumValues()
{
Type enumType = typeof(TEnum);
if(!enumType.IsEnum)
throw new ArgumentException("Type argument must be Enum type");
Array enumValues = Enum.GetValues(enumType);
return enumValues.Cast<TEnum>();
}
También se debe tener en cuenta que, dado que la publicación de C # 7.3 con restricciones de Enum es compatible fuera de la caja sin tener que realizar comprobaciones adicionales.
Así que en adelante, dado que ha cambiado la versión de idioma de su proyecto a C # 7.3, el siguiente código funcionará perfectamente:
private static T GetEnumFromString<T>(string value, T defaultValue) where T : Enum
{
// Your code goes here...
}
En caso de que no sepa cómo cambiar la versión de idioma a C # 7.3, vea la siguiente captura de pantalla:
EDIT 1 - Requiere una versión de Visual Studio y considerando ReSharper
Para que Visual Studio reconozca la nueva sintaxis, necesita al menos la versión 15.7. Puede encontrar eso también mencionado en las notas de la versión de Microsoft, consulte las Notas de la versión de Visual Studio 2017 15.7 . Gracias a @MohamedElshawaf por señalar esta pregunta válida.
Por favor, tenga en cuenta que en mi caso, ReSharper 2018.1 al momento de escribir este EDIT aún no es compatible con C # 7.3. Habiendo activado ReSharper, resalta la restricción Enum como un error que me indica que no puedo usar ''System.Array'', ''System.Delegate'', ''System.Enum'', ''System.ValueType'', ''object'' como restricción de parámetro de tipo . ReSharper sugiere como una solución rápida para eliminar la restricción ''Enum'' del tipo parámetro T del método
Sin embargo, si desactiva ReSharper temporalmente en Herramientas -> Opciones -> ReSharper Ultimate -> General , verá que la sintaxis es perfectamente correcta dado que usa VS 15.7 o superior y C # 7.3 o superior.
Tengo un requisito específico en el que debo usar enumeración con texto asociado con el valor enum. Por ejemplo, cuando uso la enumeración para especificar el tipo de error que se requiere para describir los detalles del error.
public static class XmlEnumExtension
{
public static string ReadXmlEnumAttribute(this Enum value)
{
if (value == null) throw new ArgumentNullException("value");
var attribs = (XmlEnumAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof (XmlEnumAttribute), true);
return attribs.Length > 0 ? attribs[0].Name : value.ToString();
}
public static T ParseXmlEnumAttribute<T>(this string str)
{
foreach (T item in Enum.GetValues(typeof(T)))
{
var attribs = (XmlEnumAttribute[])item.GetType().GetField(item.ToString()).GetCustomAttributes(typeof(XmlEnumAttribute), true);
if(attribs.Length > 0 && attribs[0].Name.Equals(str)) return item;
}
return (T)Enum.Parse(typeof(T), str, true);
}
}
public enum MyEnum
{
[XmlEnum("First Value")]
One,
[XmlEnum("Second Value")]
Two,
Three
}
static void Main()
{
// Parsing from XmlEnum attribute
var str = "Second Value";
var me = str.ParseXmlEnumAttribute<MyEnum>();
System.Console.WriteLine(me.ReadXmlEnumAttribute());
// Parsing without XmlEnum
str = "Three";
me = str.ParseXmlEnumAttribute<MyEnum>();
System.Console.WriteLine(me.ReadXmlEnumAttribute());
me = MyEnum.One;
System.Console.WriteLine(me.ReadXmlEnumAttribute());
}
Editar
Julien Lebosquain ya ha respondido a la pregunta . También me gustaría extender su respuesta con ignoreCase
, ignoreCase
y los argumentos opcionales, mientras agrego TryParse
y ParseOrDefault
.
public abstract class ConstrainedEnumParser<TClass> where TClass : class
// value type constraint S ("TEnum") depends on reference type T ("TClass") [and on struct]
{
// internal constructor, to prevent this class from being inherited outside this code
internal ConstrainedEnumParser() {}
// Parse using pragmatic/adhoc hard cast:
// - struct + class = enum
// - ''guaranteed'' call from derived <System.Enum>-constrained type EnumUtils
public static TEnum Parse<TEnum>(string value, bool ignoreCase = false) where TEnum : struct, TClass
{
return (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
}
public static bool TryParse<TEnum>(string value, out TEnum result, bool ignoreCase = false, TEnum defaultValue = default(TEnum)) where TEnum : struct, TClass // value type constraint S depending on T
{
var didParse = Enum.TryParse(value, ignoreCase, out result);
if (didParse == false)
{
result = defaultValue;
}
return didParse;
}
public static TEnum ParseOrDefault<TEnum>(string value, bool ignoreCase = false, TEnum defaultValue = default(TEnum)) where TEnum : struct, TClass // value type constraint S depending on T
{
if (string.IsNullOrEmpty(value)) { return defaultValue; }
TEnum result;
if (Enum.TryParse(value, ignoreCase, out result)) { return result; }
return defaultValue;
}
}
public class EnumUtils: ConstrainedEnumParser<System.Enum>
// reference type constraint to any <System.Enum>
{
// call to parse will then contain constraint to specific <System.Enum>-class
}
Ejemplos de uso:
WeekDay parsedDayOrArgumentException = EnumUtils.Parse<WeekDay>("monday", ignoreCase:true);
WeekDay parsedDayOrDefault;
bool didParse = EnumUtils.TryParse<WeekDay>("clubs", out parsedDayOrDefault, ignoreCase:true);
parsedDayOrDefault = EnumUtils.ParseOrDefault<WeekDay>("friday", ignoreCase:true, defaultValue:WeekDay.Sunday);
Antiguo
Mis antiguas mejoras en share utilizando los comentarios y los "nuevos" desarrollos:
- Usa
TEnum
para mayor claridad para los usuarios. - agregue más restricciones de interfaz para verificar restricciones adicionales
- deje que
TryParse
manejeignoreCase
con el parámetro existente (introducido en VS2010 / .Net 4) - use opcionalmente el valor
default
genérico (introducido en VS2005 / .Net 2) - use argumentos opcionales (introducidos en VS2010 / .Net 4) con valores predeterminados, para
ignoreCase
eignoreCase
Resultando en:
public static class EnumUtils
{
public static TEnum ParseEnum<TEnum>(this string value,
bool ignoreCase = true,
TEnum defaultValue = default(TEnum))
where TEnum : struct, IComparable, IFormattable, IConvertible
{
if ( ! typeof(TEnum).IsEnum) { throw new ArgumentException("TEnum must be an enumerated type"); }
if (string.IsNullOrEmpty(value)) { return defaultValue; }
TEnum lResult;
if (Enum.TryParse(value, ignoreCase, out lResult)) { return lResult; }
return defaultValue;
}
}
En java, usarías ...
SomeClass<T extends enum> {
}
Bastante sencillo, eso.
Si está bien usar el lanzamiento directo después, supongo que puedes usar la System.Enum
clase base en tu método, siempre que sea necesario. Sólo tiene que reemplazar los parámetros de tipo con cuidado. Entonces la implementación del método sería como:
public static class EnumUtils
{
public static Enum GetEnumFromString(string value, Enum defaultValue)
{
if (string.IsNullOrEmpty(value)) return defaultValue;
foreach (Enum item in Enum.GetValues(defaultValue.GetType()))
{
if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
}
return defaultValue;
}
}
Entonces puedes usarlo como:
var parsedOutput = (YourEnum)EnumUtils.GetEnumFromString(someString, YourEnum.DefaultValue);