Как использовать 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?
Как я могу это исправить ?
Спасибо.
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