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

C# 获取任何枚举值的扩展方法,c#,enums,extension-methods,.net,enum,extension,C#,Enums,Extension Methods,.net,Enum,Extension,我一直在尝试创建一个扩展方法,它可以处理任何枚举,以返回其值 而不是这样做: Enum.GetValues(typeof(BiasCode)).Cast<BiasCode>() 如果没有新的,情况会更好,但这是另一个问题 我有一个非常接近的解决方案(代码如下所示)。此代码的问题是扩展方法返回List。我想让它自己返回一个枚举值列表。返回列表并不可怕;这只是意味着我必须决定结果 甚至有可能做到这一点吗?我试图使扩展方法通用,但遇到了问题。这是我能得到的最接近的结果: using Sy

我一直在尝试创建一个扩展方法,它可以处理任何枚举,以返回其值

而不是这样做:

Enum.GetValues(typeof(BiasCode)).Cast<BiasCode>()
如果没有新的,情况会更好,但这是另一个问题

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

甚至有可能做到这一点吗?我试图使扩展方法通用,但遇到了问题。这是我能得到的最接近的结果:

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;
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共课程
{
公共静态void Main()
{
foreach(新biasCode()中的int biasCode.Values())
{
DisplayEnum((BiasCode)BiasCode);
}
}
公共静态void DisplayEnum(BiasCode BiasCode)
{
控制台写入线(biasCode);
}
}
公共枚举BiasCode
{
不详,
OC,
MPP
}
公共静态类枚举扩展
{
公共静态列表值(此枚举值)
{
var enumValues=新列表();
foreach(Enum.GetValues(theEnum.GetType())中的int-enumValue)
{
enumValues.Add(enumValue);
}
返回枚举值;
}
}

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

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();
}
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>();
}
公共静态列表值(),其中T:struct
{
var类型=类型(T);
如果(!type.IsEnum)返回null;//或引发异常
返回Enum.GetValues(type.Cast().ToList();
}
那你可以叫它

Values<BiasCode>();
value();

您可以返回相应枚举类型(使用反射创建)的实例,但其静态类型不能是
List
。这将要求
EnumType
成为方法的泛型类型参数,但该类型必须仅限于enum类型和

但是,您可以在实践中获得足够的接近度(并添加运行时检查以结束),这样您就可以编写一个如下工作的方法:

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();
}
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>();
}
公共静态IEnumerable值()
其中TEnum:struct,i可比较,i可附加,i可转换
{
var enumType=typeof(TEnum);
//可选运行时检查完整性
如果(!enumType.IsEnum)
{
抛出新ArgumentException();
}
返回Enum.GetValues(enumType.Cast();
}
您可以使用

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

我已经将方法return
IEnumerable
替换为额外LINQ-y风格的列表,但是您可以在返回值上使用
.ToList()
返回一个真实的列表。

因为您正在寻找扩展方法,这里是:

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();
   }
}
公共静态类枚举扩展
{
公共静态列表值(此T thenum)
其中T:struct,i可比较,i可附加,i可转换
{
if(!typeof(T).IsEnum)
抛出新的InvalidOperationException(string.Format(“Type{0}不是enum.”,typeof(T.FullName));
返回Enum.GetValues(theEnum.GetType()).Cast().ToList();
}
}
编辑

我将在Bob的回答中加入我的评论:


所以,我想我们都同意,没有最好的解决方案,因为不可能对枚举类型执行where子句约束。另一个解决方案是具有以下方法签名(如Bob所建议的):

公共静态列表值(此枚举值)
使用此解决方案,我们可以做得更好的是仅对枚举值进行约束。但是,与泛型解决方案相比,我们丢失了有关枚举类型的信息,我们正在调用您的扩展方法。所以我们需要再投一次。我看不出这与Bob在问题中最初发布的方法有多大区别,他返回
List
,需要将其转换回我们的枚举

最优雅的解决方案可以通过与静态检查一起使用来实现。然而,它需要使用代码契约,若要在这种情况下使用它们,可能会有点过头。这个方法在下面的线程中得到了解决:

这个怎么样

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>();
    }
}
类程序{
静态void Main(字符串[]参数)
{
BiasCode b=BiasCode.MPP;
var this=b.Values().ToList();
//…这些包含作为枚举类型的实际值
}
}
公共静态类枚举扩展
{
公共静态IEnumerable值(此T thenum),其中T:struct、IComparable、IFormattable、IConvertible
{
var enumValues=新列表();
如果(!(theEnum是Enum))
抛出新ArgumentException(“必须给我一个枚举”);
返回Enum.GetValues(typeof(T)).Cast();
}
}

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

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

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

扩展方法以获取C#

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

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>();
    }
}
公共静态类枚举,其中TEnum:struct、IComparable、IFormattable、IConvertible
{
公共静态IEnumerable GetAll()
{
var t=类型(TEnum);
如果(!t.IsEnum)
抛出新ArgumentException();
返回Enum.GetValues(t.Cast();
}
}
用法

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

public enum Test
{
    First,
    Second,
    Third
}

[TestClass]
public class EnumTests
{
    [TestMethod]
    public void MyTestMethod()
    {
        var values = Enum<Test>.GetAll();
        Assert.AreEqual(3, values.Count());
    }
}
公共枚举测试
{
第一,
第二
第三
}
[测试类]
公共类枚举测试
{
[测试方法]
公共void MyTestMethod()
{
var values=Enum.GetAll();
aresequal(3,values.Count());
}
}

你怎么称呼这个?您是否需要仅使用枚举的一个元素来创建枚举的实例
public enum Test
{
    First,
    Second,
    Third
}

[TestClass]
public class EnumTests
{
    [TestMethod]
    public void MyTestMethod()
    {
        var values = Enum<Test>.GetAll();
        Assert.AreEqual(3, values.Count());
    }
}