2010-07-28 51 views
5

我想從字符串中返回一個強類型的枚舉值。我相信有更好的方法來做到這一點。這似乎太像這樣簡單的代碼太多代碼:如何從字符串返回枚舉值?

public static DeviceType DefaultDeviceType 
    { 
     get 
     { 
      var deviceTypeString = GetSetting("DefaultDeviceType"); 
      if (deviceTypeString.Equals(DeviceType.IPhone.ToString())) 
       return DeviceType.IPhone; 
      if (deviceTypeString.Equals(DeviceType.Android.ToString())) 
       return DeviceType.Android; 
      if (deviceTypeString.Equals(DeviceType.BlackBerry.ToString())) 
       return DeviceType.BlackBerry; 
      if (deviceTypeString.Equals(DeviceType.Other.ToString())) 
       return DeviceType.Other; 
      return DeviceType.IPhone; // If no default is provided, use this default. 
     } 
    } 

想法?

根據我從社區獲得的反饋,我決定使用將字符串轉換爲枚舉的方法擴展。它需要一個參數(默認的枚舉值)。該默認值還提供了類型,因此可以推斷泛型,並且不需要使用<>來明確指定。該方法現在縮短爲:

public static DeviceType DefaultDeviceType 
    { 
     get 
     { 
      return GetSetting("DefaultDeviceType").ToEnum(DeviceType.IPhone); 
     } 
    } 

非常酷的解決方案,可以在未來重複使用。

回答

13

如果您正在處理(不可靠)用戶輸入,我喜歡使用允許默認值的擴展方法。試試看。

public static TResult ParseEnum<TResult>(this string value, TResult defaultValue) 
    { 
     try 
     { 
      return (TResult)Enum.Parse(typeof(TResult), value, true); 
     } 
     catch (ArgumentException) 
     { 
      return defaultValue; 
     } 
    } 
+0

非常酷,我喜歡提供默認的能力 - 我可能最終會使用這個。謝謝。 – 2010-07-28 18:21:16

+3

這是一個好方法。根據你的.NET版本,更新的Enum.TryParse可以讓你在擺脫try塊時保持同樣的方法。 – TechNeilogy 2010-07-28 18:23:38

+0

@TechNeilogy我正在使用.net 3.5,沒有看到TryParse方法 - 4.0必須是新的? – 2010-07-28 18:31:20

15

使用Enum.Parse()

var deviceTypeString = GetSetting("DefaultDeviceType"); 
return (DeviceType)Enum.Parse(typeof(DeviceType), deviceTypeString); 

如果輸入的是不可靠的,你要小心,因爲你會得到一個ArgumentException如果該值不能被解釋爲枚舉的值之一。

還有一個過載Parse(),允許您在進行此轉換時忽略大小寫(如果需要)。

+0

尼斯,這是更好的方式。謝謝! – 2010-07-28 18:19:25

1

我寫了這個擴展方法一旦轉換成任何任何枚舉類型從字符串,這樣你就不必一遍又一遍寫轉換代碼:

public static class StringExtensions 
    { 

    public static T ConvertToEnum<T>(this string value) 
    { 
     //Guard condition to not allow this to be used with any other type than an Enum 
     if (typeof(T).BaseType != typeof(Enum)) 
     { 
      throw new InvalidCastException(string.Format("ConvertToEnum does not support converting to type of [{0}]", typeof(T))); 
     } 


     if (Enum.IsDefined(typeof(T), value) == false) 
     { 
      //you can throw an exception if the string does not exist in the enum 
      throw new InvalidCastException(); 

      //If you prefer to return the first available enum as the default value then do this 
      Enum.GetNames(typeof (T))[0].ConvertToEnum<T>(); //Note: I haven't tested this 
     } 
     return (T)Enum.Parse(typeof(T), value); 
    } 
} 

實際使用它,你可以這樣做:

//This is a enumeration for testing 
enum MyEnumType 
{ 
    ENUM1, 
    ENUM2 
} 

//How to cast 
var myEnum = "ENUM2".ConvertToEnum<MyEnumType>(); 

myEnum在這一點上應該等於ENUM2

+0

這是光滑的!我唯一沒看到的是如何處理解析失敗時的情況,應該使用什麼默認值?也許我可以添加一個重載將默認值傳遞給擴展方法。 – 2010-07-28 18:36:07

+0

我在想如果我公開一個不採用默認的方法,那麼我可以使用第一個枚舉值(對於默認值)。你碰巧知道如何獲得第一個枚舉值,而在上面的代碼中使用泛型? – 2010-07-28 18:43:53

+0

@Paul謝謝,好吧,如果解析失敗了,我個人會想知道它,並且拋出異常。我不想返回一個默認值,因爲這可能會導致一些邏輯錯誤,當我假設解析正在工作,但它實際上是失敗的,而且實際上只是返回一個默認值。 – 7wp 2010-07-28 19:16:21