获取任何枚举值的扩展方法
本文关键字:扩展 方法 任何 枚举 获取 | 更新日期: 2023-09-27 18:04:26
我一直在尝试创建一个扩展方法,可以在任何enum上工作,以返回其值。
而不是这样做:
Enum.GetValues(typeof(BiasCode)).Cast<BiasCode>()
这样做会很好:
new BiasCode().Values()
如果没有new会更好,但这是另一个问题。
我有一个。net提琴,有一个解决方案,这是接近(代码如下所示)。这段代码的问题是扩展方法返回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;
}
}
您可以返回适当enum类型的实例(使用反射创建),但其静态类型不能为List<EnumType>
。这将要求EnumType
是该方法的泛型类型参数,但是该类型必须被约束为仅枚举类型,而这在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()
的真实列表。
你可以这样声明你的方法:
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>();
我想知道我是否错过了一些东西,因为所有的答案都使用通用方法作为解决方案的一部分。为什么不这样做呢?
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();
在编译时最好不要让Values()对字符串可用
这个怎么样
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>();
}
}
由于您正在寻找扩展方法,这里是:
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值进行约束。然而,与泛型解决方案相比,我们丢失了关于枚举类型的信息,我们在枚举类型上调用扩展方法。所以我们需要再铸一次。我看不出这和Bob在他的问题中最初发布的方法有多大区别,他返回List<int>
并需要将其强制转换回我们的enum。
获取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>();
}
}
使用var values = Enum<MyEnum>.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());
}
}
.net c#枚举扩展