Как использовать generic Tryparse с перечислением?



Я пытаюсь построить универсальную функцию, которая получает от пользователя строку и пытается разобрать ее для перечисления 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)    .


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

653   4  

4 ответов:

TryParse Метод имеет следующую сигнатуру:

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

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

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

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

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

Давным-давно, в эпоху 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;
}

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

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

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

Comments

    Ничего не найдено.