define - Cast Int para Enum genérico en C#
enum in model c# (5)
Alternativamente, si puede obtener una enumeración no como un tipo genérico, sino como un tipo, simplemente use
Enum.ToObject
https://msdn.microsoft.com/en-us/library/system.enum.toobject(v=vs.110).aspx
Similar a Cast int to enum en C # pero my enum es un parámetro de tipo genérico. ¿Cuál es la mejor manera de manejar esto?
Ejemplo:
private T ConvertEnum<T>(int i) where T : struct, IConvertible
{
return (T)i;
}
Genera el error del compilador Cannot convert type ''int'' to ''T''
El código completo es el siguiente, donde value puede contener el int o null.
private int? TryParseInt(string value)
{
var i = 0;
if (!int.TryParse(value, out i))
{
return null;
}
return i;
}
private T? TryParseEnum<T>(string value) where T : struct, IConvertible
{
var i = TryParseInt(value);
if (!i.HasValue)
{
return null;
}
return (T)i.Value;
}
Aquí hay una solución muy rápida que abusa del hecho de que el tiempo de ejecución crea múltiples instancias de clases genéricas estáticas. ¡Desata tus demonios de optimización interna!
Esto realmente brilla cuando estás leyendo Enums de una transmisión de una manera genérica. Combínelo con una clase externa que también almacena en caché el tipo subyacente de la enumeración y un BitConverter para liberar lo increíble.
void Main()
{
Console.WriteLine("Cast (reference): {0}", (TestEnum)5);
Console.WriteLine("EnumConverter: {0}", EnumConverter<TestEnum>.Convert(5));
Console.WriteLine("Enum.ToObject: {0}", Enum.ToObject(typeof(TestEnum), 5));
int iterations = 1000 * 1000 * 100;
Measure(iterations, "Cast (reference)", () => { var t = (TestEnum)5; });
Measure(iterations, "EnumConverter", () => EnumConverter<TestEnum>.Convert(5));
Measure(iterations, "Enum.ToObject", () => Enum.ToObject(typeof(TestEnum), 5));
}
static class EnumConverter<TEnum> where TEnum : struct, IConvertible
{
public static readonly Func<long, TEnum> Convert = GenerateConverter();
static Func<long, TEnum> GenerateConverter()
{
var parameter = Expression.Parameter(typeof(long));
var dynamicMethod = Expression.Lambda<Func<long, TEnum>>(
Expression.Convert(parameter, typeof(TEnum)),
parameter);
return dynamicMethod.Compile();
}
}
enum TestEnum
{
Value = 5
}
static void Measure(int repetitions, string what, Action action)
{
action();
var total = Stopwatch.StartNew();
for (int i = 0; i < repetitions; i++)
{
action();
}
Console.WriteLine("{0}: {1}", what, total.Elapsed);
}
Resultados en Core i7-3740QM con optimizaciones habilitadas:
Cast (reference): Value
EnumConverter: Value
Enum.ToObject: Value
Cast (reference): 00:00:00.3175615
EnumConverter: 00:00:00.4335949
Enum.ToObject: 00:00:14.3396366
Debería poder usar Enum.Parse
para esto:
return (T)Enum.Parse(typeof(T), i.Value.ToString(), true);
Este artículo habla sobre el análisis de enumeraciones genéricas para métodos de extensión:
La forma más simple que he encontrado es forzar la mano del compilador agregando un molde a un object
.
return (T)(object)i.Value;
public static class Extensions
{
public static T ToEnum<T>(this int param)
{
var info = typeof(T);
if (info.IsEnum)
{
T result = (T)Enum.Parse(typeof(T), param.ToString(), true);
return result;
}
return default(T);
}
}