Ähnlich wie Cast int to enum in C #, aber meine Aufzählung ist ein generischer Typparameter. Was ist der beste Weg, um damit umzugehen?
Beispiel:
private T ConvertEnum<T>(int i) where T : struct, IConvertible
{
return (T)i;
}
Erzeugt einen Compilerfehler Cannot convert type 'int' to 'T'
Der vollständige Code lautet wie folgt: Der Wert kann int oder null enthalten.
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;
}
Antworten:
Der einfachste Weg, den ich gefunden habe, besteht darin, die Hand des Compilers durch Hinzufügen eines Casts zu erzwingen
object
.return (T)(object)i.Value;
quelle
Sie sollten in der Lage sein,
Enum.Parse
dies zu verwenden:return (T)Enum.Parse(typeof(T), i.Value.ToString(), true);
Dieser Artikel befasst sich mit dem Parsen generischer Aufzählungen für Erweiterungsmethoden:
quelle
Hier ist eine sehr schnelle Lösung, die die Tatsache missbraucht, dass die Laufzeit mehrere Instanzen statischer generischer Klassen erstellt. Entfessle deine inneren Optimierungsdämonen!
Dies scheint wirklich zu leuchten, wenn Sie Enums aus einem Stream generisch lesen. Kombiniere es mit einer äußeren Klasse, die auch den zugrunde liegenden Typ der Enumeration zwischenspeichert, und einem BitConverter, um das Fantastische zu entfesseln.
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); }
Ergebnisse auf Core i7-3740QM mit aktivierten Optimierungen:
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
quelle
Expression.ConvertChecked
stattdessen verwenden, damit ein numerischer Überlauf des Bereichs des Aufzählungstyps zu einem führtOverflowException
.Wenn Sie eine Aufzählung nicht als generischen Typ, sondern als Typ erhalten können, verwenden Sie sie einfach
https://msdn.microsoft.com/en-us/library/system.enum.toobject(v=vs.110).aspx
quelle
In .NET Core ist es jetzt möglich, System.Runtime.CompilerServices.Unsafe- Code wie folgt zu verwenden:
return Unsafe.As<int, TEnum>(ref int32);
quelle
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); } }
quelle