2008-11-09 101 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();