Строка parse для перечисления типа
У меня есть тип перечисления, подобный этому в качестве примера:
public Enum MyEnum {
enum1, enum2, enum3 };
Я прочитаю строку из файла конфигурации. Мне нужно, чтобы он разбирал строку с типом MyEnum или null o не определялся. Не уверен, что будут работать следующие коды (извините за отсутствие доступа к моему VS прямо сейчас):
// example: ParseEnum<MyEnum>("ENUM1", ref eVal);
bool ParseEnum<T>(string value1, ref eVal) where T : Enum
{
bool bRet = false;
var x = from x in Enum.GetNames(typeof(T)) where
string.Equals(value1, x, StringComparison. OrdinalIgnoreCase)
select x;
if (x.Count() == 1 )
{
eVal = Enum.Parse(typeof(T), x.Item(0)) as T;
bRet = true;
}
return bRet;
}
Не уверен, что это правильно или есть другой простой способ разбора строки в значение MyEnum?
Ответы
Ответ 1
Что-то вроде:
public static class EnumUtils
{
public static Nullable<T> Parse<T>(string input) where T : struct
{
//since we cant do a generic type constraint
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Generic Type 'T' must be an Enum");
}
if (!string.IsNullOrEmpty(input))
{
if (Enum.GetNames(typeof(T)).Any(
e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant()))
{
return (T)Enum.Parse(typeof(T), input, true);
}
}
return null;
}
}
Используется как:
MyEnum? value = EnumUtils.Parse<MyEnum>("foo");
(Примечание: используется старая версия try/catch
вокруг Enum.Parse
)
Ответ 2
private enum MyEnum
{
Enum1 = 1, Enum2 = 2, Enum3 = 3, Enum4 = 4, Enum5 = 5, Enum6 = 6,
Enum7 = 7, Enum8 = 8, Enum9 = 9, Enum10 = 10
}
private static Object ParseEnum<T>(string s)
{
try
{
var o = Enum.Parse(typeof (T), s);
return (T)o;
}
catch(ArgumentException)
{
return null;
}
}
static void Main(string[] args)
{
Console.WriteLine(ParseEnum<MyEnum>("Enum11"));
Console.WriteLine(ParseEnum<MyEnum>("Enum1"));
Console.WriteLine(ParseEnum<MyEnum>("Enum6").GetType());
Console.WriteLine(ParseEnum<MyEnum>("Enum10"));
}
ВЫВОД:
//This line is empty as Enum11 is not there and function returns a null
Enum1
TestApp.Program+MyEnum
Enum10
Press any key to continue . . .
Ответ 3
Это старый вопрос, но теперь .NET 4.5 имеет Enum.TryParse().
http://msdn.microsoft.com/en-us/library/dd991317.aspx
Ответ 4
Если вы используете .NET 3.5 (или даже 2.0, если вы обрезаете метод расширения), мне повезло с техникой в этой статье:
Перечисления и строки - Прекратите безумие!
EDIT: домен ушел и теперь является фермой ссылок. Я вытащил код (немного модифицированный и добавленный со временем) из нашей кодовой базы на работе, которую вы теперь можете найти здесь:
https://gist.github.com/1305566
Ответ 5
У меня есть метод TryParseName
в UnconstrainedMelody, библиотека для методов утилиты для делегата и enum, которая использует "невыразимые" ограничения через некоторую постройку обман. (Код, использующий библиотеку, не нуждается в postbuild, чтобы быть понятным.)
Вы бы использовали его следующим образом:
Foo foo;
bool parsed = Enums.TryParseName<Foo>(name, out foo);
В настоящее время у меня нет версии без учета регистра, но я мог бы легко ввести ее, если хотите. Обратите внимание, что это не пытается анализировать числа, например. "12", как и встроенная версия, также не пытается анализировать разделенные запятыми списки флагов. Я могу добавить версию флагов позже, но я не вижу большой точки в числовой версии.
Это делается без бокса и без проверки типа времени выполнения. Наличие ограничения действительно удобно:)
Пожалуйста, дайте мне знать, если вы найдете полезный анализ без учета регистра...
Ответ 6
Я только что добавил синтаксис здесь, с обработкой исключений из здесь, чтобы создать это:
public static class Enum<T>
{
public static T Parse(string value)
{
//Null check
if(value == null) throw new ArgumentNullException("value");
//Empty string check
value = value.Trim();
if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value");
//Not enum check
Type t = typeof(T);
if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum");
return (T)Enum.Parse(typeof(T), value);
}
}
Вы можете немного обмануть его, чтобы вернуть null вместо исключения исключений.
Ответ 7
Вы можете использовать TryParse
, если вы хотите избежать использования try/catch.
MyEnum eVal;
if (Enum.TryParse("ENUM2", true, out eVal)){
// now eVal is the enumeration element: enum2
}
//unable to parse. You can log the error, exit, redirect, etc...
Я немного изменил выбранный ответ. Надеюсь, вам это понравится.
public static class EnumUtils
{
public static Nullable<T> Parse<T>(string input) where T : struct
{
//since we cant do a generic type constraint
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Generic Type 'T' must be an Enum");
}
int intVal;
if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal))
{
T eVal;
if (Enum.TryParse(input, true, out eVal))
{
return eVal;
}
}
return null;
}
}
Ответ 8
Возвращать Enum строкой, если содержит:
public static T GetEnum<T>(string s)
{
Array arr = Enum.GetValues(typeof(T));
foreach (var x in arr)
{
if (x.ToString().Contains(s))
return (T)x;
}
return default(T);
}