2008-11-09 131 views
53

在vs2008中,是否可以編寫適用於任何枚舉的擴展方法。枚舉擴展方法

我知道你可以針對特定的枚舉編寫擴展方法,但我希望能夠使用單個擴展方法進行每個枚舉。這可能嗎?

回答

80

是的,只是針對基地Enum類型的代碼,例如,

public static void Something(this Enum e) 
{ 
    // code here 
} 

的下側是,你可能最終會做這樣發現使用Enum.GetUnderlyingType真正的基本類型,鑄造下去各部門根據什麼枚舉的基本類型是一些很討厭的東西,但你可以找到一些很好的用法(例如,我們有適用於所有枚舉的IsOneOfIsCombinationOf方法)。 PS:記得在編寫這樣一種方法時,雖然不好意思,但您可以使用floatdouble作爲枚舉的基本類型,因此您需要一些特殊情況以及無符號值。

+0

你給的例子正是我想做的事情,即使是相同的名稱。 :) – 2008-11-09 22:43:26

+4

@Greg:在哪種語言中可以使用float和double作爲枚舉的基礎類型?你不能在C#中 - 你得到錯誤CS1008:類型byte,sbyte,short,ushort,int,uint,long或ulong預期 – 2008-11-09 23:01:01

+3

我知道的唯一支持它的語言是CIL。我沒有真正嘗試過證明它,因爲它看起來像一個普遍不好的想法,但看到里科附近的評論在這裏:http://en.csharp-online.net/.NET_Type_Design_Guidelines%E2%80%94Enum_Design – 2008-11-10 02:42:40

18

是的,你可以。目標擴展類型的類型爲Enum。在C#中,這將是實現爲:

public static void EnumExtension(this Enum e) 
{ 
} 

或像這樣在VB:

<Extension()> _ 
Public Sub EnumExtension(ByVal s As Enum) 
End Sub 
18

僅供參考下面是一個枚舉擴展的方法,我已經能夠使用的一個很好的例子。它實現了對枚舉一個區分大小寫的TryParse()函數:

public enum TestEnum 
{ 
    A, 
    B, 
    C 
} 

public void TestMethod(string StringOfEnum) 
{ 
    TestEnum myEnum; 
    myEnum.TryParse(StringOfEnum, out myEnum); 
} 

這裏是我參觀,以幫助想出這個代碼的兩個站點:

public static class ExtensionMethods 
{ 
    public static bool TryParse<T>(this Enum theEnum, string strType, 
     out T result) 
    { 
     string strTypeFixed = strType.Replace(' ', '_'); 
     if (Enum.IsDefined(typeof(T), strTypeFixed)) 
     { 
      result = (T)Enum.Parse(typeof(T), strTypeFixed, true); 
      return true; 
     } 
     else 
     { 
      foreach (string value in Enum.GetNames(typeof(T))) 
      { 
       if (value.Equals(strTypeFixed, 
        StringComparison.OrdinalIgnoreCase)) 
       { 
        result = (T)Enum.Parse(typeof(T), value); 
        return true; 
       } 
      } 
      result = default(T); 
      return false; 
     } 
    } 
} 

你可能會以如下方式使用它:

Case Insensitive TryParse for Enums

Extension methods for Enums

9

下面是另一個例子 - 與創建和初始化臨時變量相比,也更好的恕我直言。

public static class ExtensionMethods 
{ 
    public static void ForEach(this Enum enumType, Action<Enum> action) 
    { 
     foreach (var type in Enum.GetValues(enumType.GetType())) 
     { 
      action((Enum)type); 
     } 
    } 
} 

public enum TestEnum { A,B,C } 
public void TestMethod() 
{ 
    default(TestEnum).ForEach(Console.WriteLine); 
} 
4

您也可以實現轉換方法如下:

public static class Extensions 
{ 
    public static ConvertType Convert<ConvertType>(this Enum e) 
    { 
     object o = null; 
     Type type = typeof(ConvertType); 

     if (type == typeof(int)) 
     { 
      o = Convert.ToInt32(e); 
     } 
     else if (type == typeof(long)) 
     { 
      o = Convert.ToInt64(e); 
     } 
     else if (type == typeof(short)) 
     { 
      o = Convert.ToInt16(e); 
     } 
     else 
     { 
      o = Convert.ToString(e); 
     } 

     return (ConvertType)o; 
    } 
} 

下面是一個例子用法:

int a = MyEnum.A.Convert<int>(); 
2

有時有必要從一個枚舉轉換成其它的關於枚舉的名稱或值。下面是它如何能夠很好地與擴展方法來實現:

enum Enum1 { One = 1, Two = 2, Three = 3 }; 
enum Enum2 { Due = 2, Uno = 1 }; 
enum Enum3 { Two, One }; 

Enum2 e2 = Enum1.One.ConvertByValue<Enum2>(); 
Enum3 e3 = Enum1.One.ConvertByName<Enum3>(); 
Enum3 x2 = Enum1.Three.ConvertByValue<Enum3>(); 

public static class EnumConversionExtensions 
{ 
    public static T ConvertByName<T>(this Enum value) 
    { 
     return (T)Enum.Parse(typeof(T), Enum.GetName(value.GetType(), value)); 
    } 

    public static T ConvertByValue<T>(this Enum value) 
    { 
     return (T)((dynamic)((int)((object)value))); 
    } 
} 
1

使枚舉延伸的另一個例子 - 但這次它返回輸入枚舉類型。用法

public static IEnumerable<T> toElementsCollection<T>(this T value) where T : struct, IConvertible 
    { 
     if (typeof(T).IsEnum == false) throw new Exception("typeof(T).IsEnum == false"); 

     return Enum.GetValues(typeof(T)).Cast<T>(); 
    } 

例子:

public enum TestEnum { A,B,C }; 

TestEnum.A.toElementsCollection();