获取任何枚举值的扩展方法

时间:2014-05-21 22:09:12

标签: c# enums extension-methods

我一直在尝试创建一个可以在任何枚举上运行的扩展方法来返回它的值。

而不是这样做:

Enum.GetValues(typeof(BiasCode)).Cast<BiasCode>()

这样做会很好:

new BiasCode().Values()

没有 new 会更好,但这是另一个问题。

我有一个.NET fiddle,它有一个非常接近的解决方案(代码如下所示)。此代码的问题是扩展方法返回List<int>。我想让它返回枚举值本身的列表。返回List<int>并不可怕;这只是意味着我必须施展结果。

甚至可以这样做吗?我尝试使扩展方法通用,但遇到了问题。这与我能够得到的一样接近:

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        foreach (int biasCode in new BiasCode().Values())
        {
            DisplayEnum((BiasCode)biasCode);
        }
    }

    public static void DisplayEnum(BiasCode biasCode)
    {
        Console.WriteLine(biasCode);    
    }
}

public enum BiasCode
{
    Unknown,
    OC,
    MPP
}

public static class EnumExtensions
{
    public static List<int> Values(this Enum theEnum)
    {
        var enumValues = new List<int>();
        foreach (int enumValue in Enum.GetValues(theEnum.GetType()))
        {
            enumValues.Add(enumValue);
        }

        return enumValues;
    }
}

6 个答案:

答案 0 :(得分:6)

你可以这样声明你的方法:

public static List<T> Values<T>() where T : struct
{
    var type = typeof(T);

    if(!type.IsEnum) return null; // or throw exception

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

然后你可以称之为

Values<BiasCode>();

答案 1 :(得分:5)

您可以返回相应枚举类型的实例(使用反射创建),但其静态类型不能是List<EnumType>。这需要EnumType作为方法的泛型类型参数,但是该类型必须仅限于枚举类型和that is not possible in C#

但是,你可以在实践中得到足够的接近(并添加运行时检查以将其关闭),这样你就可以编写一个像这样工作的方法:

public static IEnumerable<TEnum> Values<TEnum>()
where TEnum : struct,  IComparable, IFormattable, IConvertible
{
    var enumType = typeof(TEnum);

    // Optional runtime check for completeness    
    if(!enumType.IsEnum)
    {
        throw new ArgumentException();
    }

    return Enum.GetValues(enumType).Cast<TEnum>();
}

您可以使用

调用
var values = Values<BiasCode>();

我已经使方法返回IEnumerable<TEnum>而不是额外LINQ-y风格的列表,但是您可以在返回值上返回一个包含.ToList()的真实列表。

答案 2 :(得分:3)

我想知道我是否遗漏了一些东西,因为所有答案都使用通用方法作为解决方案的一部分。为什么不做这样的事呢?

public static List<Enum> Values(this Enum theEnum)
{
    return Enum.GetValues(theEnum.GetType()).Cast<Enum>().ToList();
}

小提琴在这里:https://dotnetfiddle.net/FRDuvD

这种扩展方法只能用于枚举。使用泛型方法,扩展方法似乎适用于所有类型:

string someString = "x";
someString.Values();

最好不要在编译时将字符串()用于字符串。

答案 3 :(得分:1)

由于您正在寻找扩展方法,因此它是:

public static class EnumExtensions
{
   public static List<T> Values<T>(this T theEnum)
       where T : struct,  IComparable, IFormattable, IConvertible
   {
       if (!typeof(T).IsEnum) 
           throw new InvalidOperationException(string.Format("Type {0} is not enum.", typeof(T).FullName)); 

       return Enum.GetValues(theEnum.GetType()).Cast<T>().ToList();
   }
}

修改

我会在Bob的答案中加入我的评论:

所以,我认为我们都同意没有最佳解决方案,因为不可能对Enum类型执行where子句约束。另一个解决方案是使用以下方法签名(如Bob建议的那样):

public static List<Enum> Values(this Enum theEnum)

使用此解决方案我们会做得更好的是仅对Enum值进行约束。但是,与通用解决方案相比,我们丢失了有关枚举类型的信息,我们正在调用您的扩展方法。所以我们需要再次施展它。我认为这与鲍勃在他的问题中最初发布的方法之间没有太大区别,他返回List<int>并需要将其转回我们的枚举。

使用Code Contracts进行静态检查可以实现最优雅的解决方案。但是,它需要使用代码合同,如果要在这种情况下使用它们可能会有些过分。以下主题解决了这种方法:Using code contracts to make a generic to be of type enum

答案 4 :(得分:1)

这个怎么样

class Program{
    static void Main(string[] args)
    {
        BiasCode b = BiasCode.MPP;
        var these = b.Values().ToList();
        //...  these contains the actual values as the enum type
    }
}
public static class EnumExtensions
{
    public static IEnumerable<T> Values<T>(this T theEnum) where T : struct,IComparable, IFormattable, IConvertible
    {
        var enumValues = new List<T>();

        if ( !(theEnum is Enum))
            throw new ArgumentException("must me an enum");

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

答案 5 :(得分:1)

获取C#中任何枚举值的扩展方法

基于上述解决方案略有不同的方法:

sscanf()

<强>用法

public static class Enum<TEnum> where TEnum : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<TEnum> GetAll()
    {
        var t = typeof(TEnum);
        if (!t.IsEnum)
            throw new ArgumentException();

        return Enum.GetValues(t).Cast<TEnum>();
    }
}

<强>测试

var values = Enum<MyEnum>.GetAll();

OpenCV TypeError: contour is not a numpy array, neither a scalar