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());
}
}