2010-07-01 81 views
25

以下通用靜態方法需要字符串並返回枚舉如何在忽略大小寫的情況下測試枚舉是否定義?

它很好忽略案例因爲我將ignoreCase參數設置爲true。

不過,我也想測試如果枚舉存在,但enum.IsDefined方法做到這一點似乎並不具有IGNORECASE參數。

我該如何測試枚舉是否定義以及是否在相同的忽略情況下?

using System; 

namespace TestEnum2934234 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      LessonStatus lessonStatus = StringHelpers.ConvertStringToEnum<LessonStatus>("prepared"); 
      ReportStatus reportStatus = StringHelpers.ConvertStringToEnum<ReportStatus>("finished"); 

      Console.WriteLine(lessonStatus.ToString()); 
      Console.WriteLine(reportStatus.ToString()); 
      Console.ReadLine(); 
     } 
    } 

    public static class StringHelpers 
    { 
     public static T ConvertStringToEnum<T>(string text) 
     { 
      if (Enum.IsDefined(typeof(T), text)) //does not have ignoreCase parameter 
       return (T)Enum.Parse(typeof(T), text, true); 
      else 
       return default(T); 
     } 
    } 

    public enum LessonStatus 
    { 
     Defined, 
     Prepared, 
     Practiced, 
     Recorded 
    } 

    public enum ReportStatus 
    { 
     Draft, 
     Revising, 
     Finished 
    } 
} 
+3

您可能需要爲枚舉考慮默認值None。除了做法良好之外,就像現在這樣,如果您爲任一枚枚舉傳遞了一串「Foo」,就會從ConvertStringToEnum中看到有效的值。 – Marc 2010-07-01 13:11:00

回答

30
public enum MyEnum 
{ 
    Bar, 
    Foo 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var containsFoo = Enum.GetNames(typeof(MyEnum)).Any(x => x.ToLower() == "foo"); 
     Console.WriteLine(containsFoo); 
    } 
} 
27

隨着@ Darin的答案,在.NET 4.0中,enum類型現在有一個的TryParse方法:

MyEnum result; 
Enum.TryParse("bar", true, out result); 

要記住的重要事情是,有一個根本的區別在Parse vs TryParse的行爲中。解析方法會拋出異常。 TryParse方法不會。這對了解你是否有可能試圖解析許多項目非常重要。

+2

這可能會返回字符串數字值的意外結果。即Enum.TryParse(「01」,true,out result)'如果碰巧有一個值爲1的枚舉,''將返回'true'。另一方面,Darin的答案只會與枚舉名稱匹配。 – 2017-01-24 13:30:39

5

使用Enum.TryParse代替:

T val; 

if(Enum.TryParse(text, true, out val)) 
    return val; 
else 
    return default(T); 
0
public static T ConvertStringToEnum<T>(string text) 
{ 
    T returnVal; 
    try 
    { 
     returnVal = (T) Enum.Parse(typeof(T), text, true); 
    } 
    catch(ArgumentException) 
    { 
     returnVal = default(T); 
    } 
    return returnVal; 
} 
1
enum DaysCollection 
    { 
    sunday, 
    Monday, 
    Tuesday, 
    Wednesday, 
    Thursday, 
    Friday, 
    Saturday 
    } 

    public bool isDefined(string[] arr,object obj) 
    { 
     bool result=false; 
     foreach (string enu in arr) 
     { 
       result = string.Compare(enu, obj.ToString(), true) == 0; 
       if (result) 
        break; 

     } 
     return result; 


    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     object obj = "wednesday"; 
     string[] arr = Enum.GetNames(typeof(DaysCollection)).ToArray(); 

     isDefined(arr,obj); 
    } 
6

我使用Compact Framework的3.5和:

Enum.TryParse 

...不存在。它具有:

Enum.IsDefined 

..但不支持 IGNORECASE參數。 我想兩全其美,所以想出了這個(作爲一個輔助方法)...

public bool TryParse<TEnum>(string value, bool ignoreCase, ref TEnum result) where TEnum : struct 
{ 
    bool parsed; 
    try 
    { 
     result = (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase); 
     parsed = true; 
    } 
    catch { } 
    return parsed; 
} 

HTH

0

使文本相同的情況下,枚舉字符串:

enum FileExts 
{ 
    jpg, 
    pdf 
} 

if (Enum.IsDefined(typeof(T), text.tolower())) //does not have ignoreCase parameter 
    return (T)Enum.Parse(typeof(T), text, true); 
else 
    return default(T); 
3

正如其他人所說的那樣,您可能只需使用Enum.TryParse即可脫身。

但是,如果你想有一個更強大的/一般的轉換,讓您更將大於只是字符串,那麼你還需要使用Enum.IsDefined,不幸的是,當你發現,是不區分大小寫。

Enum.TryParse(可以)不區分大小寫。但不幸的是,它允許超出範圍的整數通過!

所以解決方案是一起使用它們(而且順序很重要)。

我寫了一個擴展方法來做到這一點。它允許從字符串,int/int?和任何其他枚舉/枚舉轉換?鍵入像這樣:

string value1 = "Value1"; 
Enum2 enum2 = value1.ParseToEnum<Enum2>(); 
Debug.Assert(enum2.ToString() == value1); 

Enum1 enum1 = Enum1.Value1; 
enum2 = enum1.ParseToEnum<Enum2>(); 
Debug.Assert(enum2.ToString() == enum1.ToString()); 

int value2 = 1; 
enum2 = value2.ParseToEnum<Enum2>(); 
Debug.Assert(enum2.GetHashCode() == value2); 

這裏的方法的心臟。這是解決你問題的轉換部分。變量valueobject的類型,因爲我有那些以不同類型爲主要輸入的「超載」(請參閱​​上文),但是如果只是這樣,您可以使用類型爲string的變量來完成此操作(顯然會更改value.ToString()value)。

if (value != null) 
{ 
    TEnum result; 
    if (Enum.TryParse(value.ToString(), true, out result)) 
    { 
     // since an out-of-range int can be cast to TEnum, double-check that result is valid 
     if (Enum.IsDefined(typeof(TEnum), result.ToString())) 
     { 
      return result; 
     } 
    } 
} 

還有很多東西要我的擴展方法...它允許你指定默認值,處理超出範圍的整數蠻好的,完全不區分大小寫。如果有人感興趣,我可以發佈更多。

+1

對我來說,關鍵是使用TryParse的輸出結果.ToString;謝謝。其他人建議只有TryParse會錯過超出範圍的整數,從而導致誤報。 – Syntax 2017-11-15 04:49:25

0

我有一個類似的關注,並使用.Enum.TryPase(與不區分大小寫的標誌設置爲true)和Enum.IsDefined的組合。考慮下面的簡化,將輔助類:

public static class StringHelpers 
{ 
    public static T ConvertStringToEnum<T>(string text) 
    { 
     T result; 
     return Enum.TryParse(text, true, out result) 
      && Enum.IsDefined(result.ToString()) 
       ? result 
       : default(T); 
    } 
} 

雖然我們在這,因爲輔助類是靜態的,方法是靜態的 - 我們可以作出這樣的擴展方法上string

public static class StringExtensions 
{ 
    public static TEnum ToEnum<TEnum>(this string text) 
     where TEnum : struct, IComparable, IFormattable, IConvertible 
    { 
     TEnum result = default(TEnum); 
     return !string.IsNullOrWhiteSpace(text) 
      && Enum.TryParse(text, true, out result) 
      && Enum.IsDefined(typeof(TEnum), result.ToString()) 
       ? result 
       : default(TEnum); 
    } 
} 

在這裏,我創建了一個.NET Fiddle,清楚地表明瞭這一點。