Общая версия Enum.Parse в С#
Я регулярно задавался вопросом, почему С# еще не выполнил Generic Enum.Parse
Скажем, у меня
enum MyEnum
{
Value1,
Value2
}
И из файла XML/DB я хочу создать Enum.
MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true);
Не удалось ли это реализовать как-то вроде
MyEnum cal = Enum.Parse<MyEnum>("value1");
Это может показаться небольшой проблемой, но кажется, что она упускается из виду.
Любые мысли?
Ответы
Ответ 1
Он уже реализован в .NET 4;) Посмотрите здесь.
MyEnum cal;
if (!Enum.TryParse<MyEnum>("value1", out cal))
throw new Exception("value1 is not valid member of enumeration MyEnum");
Также обсуждение здесь содержит некоторые интересные моменты.
Ответ 2
И в желаемом синтаксисе вопроса:
MyEnum cal = Toolkit.Parse<MyEnum>("value1");
Примечание. Поскольку С# запрещает вам добавлять статические расширения, вы должны разместить эту функцию в другом месте. Я использую статический класс Toolkit
, который содержит все эти полезные биты:
/// <summary>
/// Converts the string representation of the name or numeric value of one or
// more enumerated constants to an equivalent enumerated object.
/// </summary>
/// <typeparam name="TEnum">An enumeration type.</typeparam>
/// <param name="value">A string containing the name or value to convert.</param>
/// <returns>An object of type TEnum whose value is represented by value</returns>
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception>
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or-
/// value is either an empty string or only contains white space.-or-
/// value is a name, but not one of the named constants defined for the enumeration.</exception>
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception>
public static TEnum Parse<TEnum>(String value) where TEnum : struct
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
Ответ 3
Хотя ограничение на System.Enum
запрещено С#, оно разрешено в .NET, а С# может использовать типы или методы с такими ограничениями. См. Jon Skeet библиотека Unconstrained Melody, которая содержит код, который делает именно то, что вы хотите.
Ответ 4
public class EnumHelper
{
public static T? TryParse<T>(string text)
where T: struct
{
if (string.IsNullOrEmpty(text))
{
return null;
}
T r;
if (Enum.TryParse<T>(text, out r))
{
return r;
}
return null;
}
}
Ответ 5
Немного измененная версия ответа @ian-boyd, используя метод расширения, чтобы избежать необходимости указывать имя статического класса в вызове:
MyEnum cal = "value1".Parse<MyEnum>();
/// <summary>
/// Converts the string representation of the name or numeric value of one or
// more enumerated constants to an equivalent enumerated object.
/// </summary>
/// <typeparam name="TEnum">An enumeration type.</typeparam>
/// <returns>An object of type TEnum whose value is represented by value</returns>
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception>
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or-
/// value is either an empty string or only contains white space.-or-
/// value is a name, but not one of the named constants defined for the enumeration.</exception>
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception>
public static TEnum Parse<TEnum>(this String value) where TEnum : struct
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
Ответ 6
Пока немного настраиваем некоторые методы, пытаясь создать нечто похожее на исходное предложение:
MyEnum cal = Enum.Parse<MyEnum>("value1");
мне показалось, что этот синтаксис невозможен в С#, так как тип Enum считается непустым.
Если мы вызываем метод "Enum.TryParse", передавая значение, не соответствующее элементу перечисления,
значение "Enum" по умолчанию будет возвращено в переменной "out". Вот почему нам нужно тестировать
сначала результат "Enum.TryParse", так как просто вызов
MyEnum cal;
Enum.TryParse<MyEnum>("value1", out cal);
и проверка значения "cal" не всегда даст надежный результат.