2009-09-15 152 views
16

我有一个枚举类型这样为例:解析字符串枚举类型

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价值?

+0

退房Enum.TryParse,如[此帖](http://www.codeducky.org/ins-提到奏-C-枚举/)。 – ChaseMedallion 2014-07-20 20:25:06

回答

31

什么是这样的:

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

+1

在正常的程序流程中使用异常处理并不是一个好主意... – 2009-09-15 03:38:51

+1

@Mark我知道,但在这种情况下确实很容易:) – 2009-09-15 03:39:19

+0

@Mark确实很好 - try/catch很少是一个好东西理念。编辑后的版本比问题中的更有效率,因为它只能进行一次部分枚举而不是3次。 – 2009-09-15 03:48:25

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

OUTPUT:

//This line is empty as Enum11 is not there and function returns a null 
Enum1 
TestApp.Program+MyEnum 
Enum10 
Press any key to continue . . . 
2

如果你使用.NET 3.5(或2.0甚至,如果你修剪出的扩展方法),我有很大的运气与本文中的技术:

枚举和字符串 - 停止疯狂!

编辑:域不见了,现在是一个链接农场。我从我们的工作的代码库,你现在可以在这里找到拉到代码(略作修改,并添加到随着时间的推移):

https://gist.github.com/1305566

+2

现在参考指向链接场。我最初把你变成了一个人,但你是很高的代表,所以我猜你不是故意这样做的,而且你不应该因为你的控制之外的内容发生什么而受到惩罚。我自己搜索了这篇文章,但没有把任何事情变得明显起来。你能否看到这个内容是否有更好的链接? – 2011-04-12 19:38:58

+0

@MichaelBlackburn:看起来这个域名消失的人。我将在星期一检查我们的代码库,看看我能否找到我从文章中借用的内容。 – 2011-10-22 03:19:24

2

我在UnconstrainedMelody一个TryParseName方法,用于委托和枚举实用程序库通过某些构建后的技巧使用“不可压缩的”约束的方法。 (代码使用库不需要postbuild,仅仅是明确的。)

你会使用这样的:

Foo foo; 
bool parsed = Enums.TryParseName<Foo>(name, out foo); 

我目前没有一个不区分大小写的版本,但是如果你愿意,我可以轻松地推出一个。请注意,此不会尝试解析数字,例如“12”像内置版本一样,也不尝试解析逗号分隔的标志列表。我稍后可能会添加标志版本,但我在数字版本中看不到多少点。

这是在没有装箱和没有执行时间类型检查的情况下完成的。具有约束是非常方便的:)

请让我知道如果你会发现一个不区分大小写的解析非常有用......

+0

@Jon Skeet,你可能会引入额外的重载方法让用户选择区分大小写或不区分大小写。 – 2009-09-15 13:08:49

+0

@Joh Skeet,不知道你的方法应该是(name,ref foo)还是不。如果tryparse失败,应该怎么做?第一个枚举值?我认为最好让用户初始化它,如果失败则不要更改它。我明白你试着让这个方法与TryParse(name,out value)一致。 – 2009-09-15 13:14:03

+1

如果'TryParse'失败,它将是'default(Foo)',这与'TryParse','TryGetValue'等一致。如果我不一致,我可能会返回一个'Nullable '。我会考虑引入一个用于不区分大小写的匹配的新重载 - 或者可能采用一个StringComparer(或类似的)来允许选择文化敏感度。 – 2009-09-15 13:21:12

1

我刚刚从合并的here语法,除从here处理,创建这个:

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而不是抛出异常。

+0

@Benjol,我喜欢你使用type.Isum来检查它的类型。 – 2009-09-15 13:18:13

1

如果您想避免使用try/catch,则可以使用TryParse

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

要通过字符串返回枚举,如果包含:

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