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

Как использовать общий Tryparse с Enum?

Я пытаюсь создать общую функцию, которая получается из пользовательской строки, и попытаться разобрать ее на Enum valuse следующим образом:

private Enum getEnumStringEnumType(Type i_EnumType)
    {
        string userInputString = string.Empty;
        Enum resultInputType;
        bool enumParseResult = false;

        while (!enumParseResult)
        {                
            userInputString = System.Console.ReadLine();
            enumParseResult = Enum.TryParse(userInputString, true, out resultInputType);
        }
    }

Но я получаю:

The type 'System.Enum' must be a non-nullable value type in order to use it as parameter 'TEnum' in the generic type or method 'System.Enum.TryParse<TEnum>(string, bool, out TEnum)    .

Ошибка означает, что мне нужно декалировать конкретный Enum для resultInputType? Как я могу это исправить? Спасибо.

4b9b3361

Ответ 1

TryParse method имеет следующую подпись:

TryParse<TEnum>(string value, bool ignoreCase, out TEnum result)
    where TEnum : struct

Он имеет параметр типового типа TEnum, который должен быть структурой и используется для определения типа анализируемого перечисления. Если вы не укажете его явно (как и вы), он примет тип того, что вы предоставляете, как аргумент result, который в вашем случае имеет тип Enum (а не тип самого перечисления).

Обратите внимание, что Enum является классом (несмотря на то, что он наследует от ValueType), и поэтому он не удовлетворяет требованию, чтобы TEnum является структурой.

Вы можете решить эту проблему, удалив параметр Type и предоставив методу общий параметр типа с теми же ограничениями (т.е. struct) в качестве параметра типового типа в функции TryParse.

Итак, попробуйте это, где я назвал параметр типового типа TEnum:

private static TEnum GetEnumStringEnumType<TEnum>()
    where TEnum : struct
{
    string userInputString = string.Empty;
    TEnum resultInputType = default(TEnum);
    bool enumParseResult = false;

    while (!enumParseResult)
    {                
        userInputString = System.Console.ReadLine();
        enumParseResult = Enum.TryParse(userInputString, true, out resultInputType);
    }
    return resultInputType;
}

Чтобы вызвать метод, используйте:

GetEnumStringEnumType<MyEnum>();

Ответ 2

Вы должны сделать общий метод:

private T getEnumStringEnumType<T>() where T : struct, IConvertible
    {
        string userInputString = string.Empty;
        T resultInputType = default(T);
        bool enumParseResult = false;

        while (!enumParseResult)
        {
            userInputString = System.Console.ReadLine();
            enumParseResult = Enum.TryParse<T>(userInputString, out resultInputType);
        }

        return resultInputType;
    }

использование:

public enum myEnum { val1, val2 }

myEnum enumValue = getEnumStringEnumType<myEnum>();

Ответ 3

Enum.TryParse - это общий метод, который означает, что его общие параметры типа должны быть известны во время компиляции. Это, в свою очередь, означает, что да, вам нужно объявить resultInputType как конкретный тип перечисления для компилируемого кода.

Если вы думаете об этом, исходный код немного оптимистичен: нигде он не говорит, какой тип перечисления должен быть проверен для члена с именем, равным userInputString. Как TryParse работать без этой информации?

Ответ 4

Давным-давно в Visual Studio 2005 я создал свой собственный метод TryParse на Enum. Я только недавно обнаружил реализацию 2008 года, и я не доволен ее ограничительной способностью, особенно учитывая, что это метод TRY PARSE; что программист тестирует ввод!

Как правило, я предпочитаю использовать методы, которые доверяют программисту, чтобы знать, что он делает:)

Моя реализация такова:

public static bool EnumTryParse<T>(string input, out T theEnum)
{
    foreach (string en in Enum.GetNames(typeof(T)))
    {
        if (en.Equals(input, StringComparison.CurrentCultureIgnoreCase))
        {
            theEnum = (T)Enum.Parse(typeof(T), input, true);
            return true;
        }
    }

    theEnum = default(T);
    return false;
}

Отсутствие того, где T: struct ставит доверие в руки разработчика, но позволяет компилировать с неизвестными общими перечислениями.

В качестве альтернативы вы можете создать метод looping для Enum.GetValues, если вы хотите сделать целочисленное сравнение при преобразовании в указанное перечисление.

Надеюсь, что это поможет.

Ответ 5

Метод расширения строки

public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){

if (string.IsNullOrEmpty(value))return defaultValue;

return Enum.Parse(typeof(TEnum), value, true);}