Как использовать общий 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?
Как я могу это исправить?
Спасибо.
Ответы
Ответ 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);}