2010-02-11 5 views
36

я регулярно задавался вопросом, почему C# еще не implemeted с Generic Enum.ParseGeneric версия Enum.Parse в C#

Допустим, у меня есть

enum MyEnum 
{ 
    Value1, 
    Value2 
} 

И из файла XML/DB вход I хотите создать Enum.

MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true); 

Может не было реализовано как нечто вроде

MyEnum cal = Enum.Parse<MyEnum>("value1"); 

Это может показаться небольшой вопрос, но мне кажется, как упускается один.

Любые мысли?

ответ

30

Он уже реализован в .NET 4;) Посмотрите here.

MyEnum cal; 
if (!Enum.TryParse<MyEnum>("value1", out cal)) 
    throw new Exception("value1 is not valid member of enumeration MyEnum"); 

Также в обсуждении here содержатся некоторые интересные моменты.

+6

Эта ссылка на нетипичных ' Метод Enum.Parse'. Вы имели в виду ссылку на новый метод 'Enum.TryParse '? http://msdn.microsoft.com/en-us/library/system.enum.tryparse%28VS.100%29.aspx –

+3

Интересно, что они ограничивали его struct, new() вместо добавления нового ограничения перечисления на язык. –

+0

Простите, я уже это исправил, это именно то, что я имел в виду;) –

6

Хотя ограничение на System.Enum запрещено C#, допускается использование в .NET и C# типы или методы с такими ограничениями. См. Библиотеку Unconstrained Melody Jon Skeet, которая содержит код, который делает именно то, что вы хотите.

+18

Humbug, я даже не могу подключить собственную библиотеку, если кто-то не попал туда первым;) –

16

И в желаемом синтаксисом вопроса:

MyEnum cal = Toolkit.Parse<MyEnum>("value1"); 

Примечание: Поскольку C# запрещает вам добавлять статические расширения, вы должны разместить функцию в другом месте. я использую статический 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); 
} 
0

Хотя настройки немного с некоторыми методами, пытаясь создать что-то похожее на первоначальное предложение:

MyEnum cal = Enum.Parse<MyEnum>("value1"); 

мне казалось, что этот синтаксис невозможен в C#, так как тип Enum обрабатывается как недействительный.

Если мы вызываем метод «Enum.TryParse», передавая значение, не соответствующее элементу перечисления, значение «Enum» по умолчанию будет возвращено в переменной «out». Вот почему мы должны проверить результат «Enum.TryParse» первый, так как просто называя

MyEnum cal; 
Enum.TryParse<MyEnum>("value1", out cal); 

и проверки «кал» значение не всегда дает надежный результат.

+3

общий «Parse» может просто быть оберткой вокруг «TryParse» и бросать «ArgumentException», если 'TryParse' возвращает' false'. –

+0

Он может просто повысить исключение вместо значения по умолчанию. То же самое, что и для универсальной версии Parse. – Maxim

+0

Идея состоит в том, чтобы избежать (по возможности) обработки исключений, который считается анти-шаблоном для управления потоком (ссылка https://web.archive.org/web/20140430044213/http://c2.com/cgi- бен/вики? DontUseExceptionsForFlowControl). Согласно спецификации API, метод Enum.TryParse «устраняет необходимость обработки исключений при анализе строкового представления значения перечисления». (https://msdn.microsoft.com/en-us//library/dd991317(v=vs.110).aspx) –

2
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; 
    } 
} 
1

Слегка модифицированная версия @ ответ Иэн-Бойд, используя метод расширения, чтобы избежать необходимости указывать имя статического класса в вызове:

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