Подтвердить что ты не робот

Вставить Int в Generic Enum в С#

Подобно Cast int для перечисления в С#, но мое перечисление является параметром Generic Type. Каков наилучший способ справиться с этим?

Пример:

private T ConvertEnum<T>(int i) where T : struct, IConvertible
{
    return (T)i;
}

Создает ошибку компилятора Cannot convert type 'int' to 'T'

Полный код выглядит следующим образом, где значение может содержать int или 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;
}
4b9b3361

Ответ 1

Самый простой способ, который я нашел, - заставить команду компилятора добавить приведение к object.

return (T)(object)i.Value;

Ответ 2

Здесь очень быстрое решение, которое злоупотребляет тем фактом, что среда выполнения создает несколько экземпляров статических родовых классов. Развяжите свои внутренние демоны оптимизации!

Это действительно сияет, когда вы читаете Enums из потока в общем виде. Объединитесь с внешним классом, который также кэширует базовый тип enum и BitConverter, чтобы развязать удивительный.

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

Результаты по Core i7-3740QM с включенными оптимизациями:

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

Ответ 4

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