枚举的扩展方法,而不是枚举的实例

我有一个枚举我的东西是这样的:

public enum Things { OneThing, AnotherThing } 

我想为这个枚举编写一个扩展方法(类似于这里的Prize的答案 ),但是当这个方法在枚举的一个实例上工作时,ala

 Things thing; var list = thing.ToSelectList(); 

我希望它在实际枚举上工作,而不是:

 var list = Things.ToSelectList(); 

我可以做

 var list = default(Things).ToSelectList(); 

但我不喜欢那个:)

我已经接近以下扩展方法:

 public static SelectList ToSelectList(this Type type) { if (type.IsEnum) { var values = from Enum e in Enum.GetValues(type) select new { ID = e, Name = e.ToString() }; return new SelectList(values, "Id", "Name"); } else { return null; } } 

像这样使用:

 var list = typeof(Things).ToSelectList(); 

我们能做得比这更好吗?

扩展方法只适用于实例,所以不能完成,但是有一些精心挑选的类/方法名称和generics,你可以得到一个看起来一样好的结果:

 public class SelectList { // Normal SelectList properties/methods go here public static SelectList Of<T>() { Type t = typeof(T); if (t.IsEnum) { var values = from Enum e in Enum.GetValues(type) select new { ID = e, Name = e.ToString() }; return new SelectList(values, "Id", "Name"); } return null; } } 

那么你可以得到你的select列表像这样:

 var list = SelectList.Of<Things>(); 

海事组织这比Things.ToSelectList()更好的读取。

没有。

你可以做的最好的是把它放在一个静态类,如下所示:

 public static class ThingsUtils { public static SelectList ToSelectList() { ... } } 

Aaronaught的答案真的很棒,基于这个我做了以下的实现:

 public class SelectList { public static IEnumerable<Enum> Of<T>() where T : struct, IConvertible { Type t = typeof(T); if (t.IsEnum) { return Enum.GetValues(t).Cast<Enum>(); } throw new ArgumentException("<T> must be an enumerated type."); } } 

在我看来,这样做更安全一些,几乎只能用Enums来调用它,当然,如果你想要一个无例外的版本,你可以直接返回null。

我使用“types”而不是“枚举”来添加扩展名。 然后我可以从方法中获取任何types的列表。 这里它返回string值:

  public static string[] AllDescription(this Type enumType) { if (!enumType.IsEnum) return null; var list = new List<string>(); var values = Enum.GetValues(enumType); foreach (var item in values) { // add any combination of information to list here: list.Add(string.Format("{0}", item)); //this one gets the values from the [Description] Attribute that I usually use to fill drop downs //list.Add(((Enum) item).GetDescription()); } return list.ToArray(); } 

后来我可以用这个语法来得到我想要的:

 var listOfThings = typeof (Things).AllDescription(); 

@Aarounaught有一个非常好的答案。 为了扩大他的答案,你甚至可以使其更通用。 我在全球图书馆有这个…

 public static IQueryable GetAllEnumValues<T>() { IQueryable retVal = null; Type targetType = typeof(T); if(targetType.IsEnum) { retVal = Enum.GetValues(targetType).AsQueryable(); } return retVal; } 

现在,您已经从SelectList类中分离了这个function。 所以你可以在你的SelectList方法或者其他任何地方调用它。

 public class SelectList { public static SelectList Of<T> { IQueryable enumValues = GetAllEnumValues<T>(); var values = from Enum e in enumValues select new { ID = e, Name = e.ToString() }; return new SelectList(values, "Id", "Name"); } } 

在我看来,这是最干净的方式。 为什么?

  • 它适用于任何System.Enum
  • 扩展方法本身更清洁。
  • 要叫它,你只需添加new ,这是一个小的折衷(因为它必须有一个实例才能工作。
  • 你不会传递null ,如果你试图用另一种types的话,它实际上不会被编译。

用法:

 (new Things()).ToSelectList() 

扩展方法:

 [Extension()] public SelectList ToSelectList(System.Enum source) { var values = from Enum e in Enum.GetValues(source.GetType) select new { ID = e, Name = e.ToString() }; return new SelectList(values, "Id", "Name"); } 

我认为,最接近的是虚拟的东西,像枚举一样工作,而不是一个枚举。 下面是我想到的 – 在枚举上使用静态方法似乎有很多工作要做,尽pipe我理解它的编程吸引力:

  public class PseudoEnum { public const int FirstValue = 1; private static PseudoEnum FirstValueObject = new PseudoEnum(1); public const int SecondValue = 2; private static PseudoEnum SecondValueObject = new PseudoEnum(2); private int intValue; // This prevents instantation; note that we cannot mark the class static private PseudoEnum() {} private PseudoEnum(int _intValue) { intValue = _intValue; } public static implicit operator int(PseudoEnum i) { return i.intValue; } public static implicit operator PseudoEnum(int i) { switch (i) { case FirstValue : return FirstValueObject; case SecondValue : return SecondValueObject; default: throw new InvalidCastException(); } } public static void DoSomething(PseudoEnum pe) { switch (pe) { case PseudoEnum.FirstValue: break; case PseudoEnum.SecondValue: break; } } }