How do I convert the following Enum to a List of strings?
[Flags]
public enum DataSourceTypes
{
None = 0,
Grid = 1,
ExcelFile = 2,
ODBC = 4
};
I couldn't find this exact question, this Enum to List is the closest but I specifically want List<string>?
Use Enum's static method, GetNames. It returns a string[], like so:
Enum.GetNames(typeof(DataSourceTypes))
If you want to create a method that does only this for only one type of enum, and also converts that array to a List, you can write something like this:
public List<string> GetDataSourceTypes()
{
return Enum.GetNames(typeof(DataSourceTypes)).ToList();
}
You will need Using System.Linq; at the top of your class to use .ToList()
I want to add another solution:
In my case, I need to use a Enum group in a drop down button list items. So they might have space, i.e. more user friendly descriptions needed:
public enum CancelReasonsEnum
{
[Description("In rush")]
InRush,
[Description("Need more coffee")]
NeedMoreCoffee,
[Description("Call me back in 5 minutes!")]
In5Minutes
}
In a helper class (HelperMethods) I created the following method:
public static List<string> GetListOfDescription<T>() where T : struct
{
Type t = typeof(T);
return !t.IsEnum ? null : Enum.GetValues(t).Cast<Enum>().Select(x => x.GetDescription()).ToList();
}
When you call this helper you will get the list of item descriptions.
List<string> items = HelperMethods.GetListOfDescription<CancelReasonEnum>();
ADDITION:
In any case, if you want to implement this method you need :GetDescription extension for enum. This is what I use.
public static string GetDescription(this Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =Attribute.GetCustomAttribute(field,typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
/* how to use
MyEnum x = MyEnum.NeedMoreCoffee;
string description = x.GetDescription();
*/
}
In my case, I need to convert it as SelectItem for Checkbox and Radio Button
public class Enum<T> where T : struct, IConvertible
{
public static List<SelectItem> ToSelectItems
{
get
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
var values = Enum.GetNames(typeof(T));
return values.Select((t, i) => new SelectItem() {Id = i, Name = t}).ToList();
}
}
}
Related
I need to create a SelectList from any Enum in my project.
I have the code below which I create a select list from a specific enum, but I'd like to make an extension method for ANY enum. This example retrieves the value of the DescriptionAttribute on each Enum value
var list = new SelectList(
Enum.GetValues(typeof(eChargeType))
.Cast<eChargeType>()
.Select(n => new
{
id = (int)n,
label = n.ToString()
}), "id", "label", charge.type_id);
Referencing this post, how do I proceed?
public static void ToSelectList(this Enum e)
{
// code here
}
What I think you are struggling with, is the retrieval of the description. I'm sure once you have those that you can define your final method which gives your exact result.
First, if you define an extension method, it works on a value of the enum, not on the enum type itself. And I think, for easy of usage, you would like to call the method on the type (like a static method). Unfortunately, you cannot define those.
What you can do is the following. First define a method which retrieves the description of the enum value, if it has one:
public static string GetDescription(this Enum value) {
string description = value.ToString();
FieldInfo fieldInfo = value.GetType().GetField(description);
DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0) {
description = attributes[0].Description;
}
return description;
}
Next, define a method which takes all values of an enum, and use the previous method to look up the value which we want to show, and return that list. The generic argument can be inferred.
public static List<KeyValuePair<TEnum, string>> ToEnumDescriptionsList<TEnum>(this TEnum value) {
return Enum
.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Select(x => new KeyValuePair<TEnum, string>(x, ((Enum)((object)x)).GetDescription()))
.ToList();
}
And finally, for ease of usage, a method to call it directly without value. But then the generic argument is not optional.
public static List<KeyValuePair<TEnum, string>> ToEnumDescriptionsList<TEnum>() {
return ToEnumDescriptionsList<TEnum>(default(TEnum));
}
Now we can use it like this:
enum TestEnum {
[Description("My first value")]
Value1,
Value2,
[Description("Last one")]
Value99
}
var items = default(TestEnum).ToEnumDescriptionsList();
// or: TestEnum.Value1.ToEnumDescriptionsList();
// Alternative: EnumExtensions.ToEnumDescriptionsList<TestEnum>()
foreach (var item in items) {
Console.WriteLine("{0} - {1}", item.Key, item.Value);
}
Console.ReadLine();
Which outputs:
Value1 - My first value
Value2 - Value2
Value99 - Last one
Late to the party, but since there is no accepted answer and it might help others:
As #Maarten mentioned, an extension method works on the value of an enum, not the enum type itelf, so as with Maarteen's soultion you can create a dummy or default value to call the extension method on, however, you may find, as I did, that it is simpler to just use a static helper method like so:
public static class EnumHelper
{
public static SelectList GetSelectList<T>(string selectedValue, bool useNumeric = false)
{
Type enumType = GetBaseType(typeof(T));
if (enumType.IsEnum)
{
var list = new List<SelectListItem>();
// Add empty option
list.Add(new SelectListItem { Value = string.Empty, Text = string.Empty });
foreach (Enum e in Enum.GetValues(enumType))
{
list.Add(new SelectListItem { Value = useNumeric ? Convert.ToInt32(e).ToString() : e.ToString(), Text = e.Description() });
}
return new SelectList(list, "Value", "Text", selectedValue);
}
return null;
}
private static bool IsTypeNullable(Type type)
{
return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
}
private static Type GetBaseType(Type type)
{
return IsTypeNullable(type) ? type.GetGenericArguments()[0] : type;
}
You would create the select list like this:
viewModel.ProvinceSelect = EnumHelper.GetSelectList<Province>(model.Province);
or using the optional numeric values instead of strings:
viewModel.MonthSelect = EnumHelper.GetSelectList<Month>(model.Month,true);
The basic idea for this I got from here, though I changed it to suit my needs. One thing I added was the ability to optionally use ints for the value. I also added an enum extension to get the description attribute which is based on this blog post:
public static class EnumExtensions
{
public static string Description(this Enum en)
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
return ((DescriptionAttribute)attrs[0]).Description;
}
}
return en.ToString();
}
}
Since enum can't have extensions pinned to the entire collection a convenient way to extend the Enum base class is with a static typed class. This will allow concise code such as:
Enum<MyCustomEnumType>.GetSelectItems();
Which can be achieved with the following code:
public static class Enum<T>
{
public static SelectListItem[] GetSelectItems()
{
Type type = typeof(T);
return
Enum.GetValues(type)
.Cast<object>()
.Select(v => new SelectListItem() { Value = v.ToString(), Text = Enum.GetName(type, v) })
.ToArray();
}
}
Since enum do not have a shared interface Type misuse is possible, but the class name Enum should dispell any confusion.
Here is a corrected [type casted value to int] and simplified [uses tostring override instead of getname] version of Nathaniels answer that returns a List instead of an array:
public static class Enum<T>
{
//usage: var lst = Enum<myenum>.GetSelectList();
public static List<SelectListItem> GetSelectList()
{
return Enum.GetValues( typeof(T) )
.Cast<object>()
.Select(i => new SelectListItem()
{ Value = ((int)i).ToString()
,Text = i.ToString() })
.ToList();
}
}
At start, we have this basic enum.
public enum E_Levels {
[ValueOfEnum("Low level")]
LOW,
[ValueOfEnum("Normal level")]
NORMAL,
[ValueOfEnum("High level")]
HIGH
}
And I would like to get a List<string> whatever the enum. Something like Extensions.GetValuesOfEnum<E_Levels>() which could return a List<string> with "Low level", "Normal level" and "High level" in it.
StackOF helped me to get one value attribute :
public static class Extensions {
public static string ToValueOfEnum(this Enum value) {
FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
ValueOfEnum[] attribs = fieldInfo.GetCustomAttributes(typeof(ValueOfEnum), false) as ValueOfEnum[];
return attribs.Length > 0 ? attribs[0].value : null;
}
}
And I can call this method whatever the enum : E_Levels.LOW.ToValueOfEnum().
Furthermore, StackOF helped me to get a List<string> for a specific enum.
I made this method in a controller :
private List<string> GetLevels() {
List<string> levelsToReturn = new List<string>();
var levels = Enum.GetValues(typeof(E_Levels)).Cast<E_Levels>();
foreach(E_Levels l in levels)
levelsToReturn.Add(l.ToValueOfEnum());
return levelsToReturn;
}
But this way requires me to rewrite the same method for each enum.
So I tried to add this generic method my class Extensions :
public static class Extensions {
public static string ToValueOfEnum(this Enum value) {...}
public static List<string> GetValuesOf<T>() {
List<string> levelsToReturn = new List<string>();
var levels = Enum.GetValues(typeof(T)).Cast<T>();
foreach(T l in levels)
levelsToReturn.Add(l.ToValueOfEnum());
return levelsToReturn;
}
}
But in my foreach, .ToValueOfEnum() is an unknown method.
So I am in trouble, I hoped I could find a way to not rewrite again and again the same method for each enum...
Let's try to keep this more general purpose.
I have an extension method that could grab attributes off of enum values. This would give you quick access to the attributes.
public static class EnumExtensions
{
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
var type = value.GetType();
var name = Enum.GetName(type, value);
return type.GetField(name)
.GetCustomAttributes(false)
.OfType<TAttribute>()
.SingleOrDefault();
}
}
Using this, you could create some queries to get what you want.
var valuesOfLevels =
Enum.GetValues(typeof(E_Levels)).Cast<E_Levels>()
.Select(level => level.GetAttribute<ValueOfEnumAttribute>().Value);
So your GetValuesOf() method (which is not a great name for such a specialty method IMHO) can be written like this:
public static List<string> GetValuesOf<TEnum>()
where TEnum : struct // can't constrain to enums so closest thing
{
return Enum.GetValues(typeof(TEnum)).Cast<Enum>()
.Select(val => val.GetAttribute<ValueOfEnumAttribute>().Value)
.ToList();
}
Now you may call the method like so:
var levelValues = GetValueOf<E_Levels>();
// levelValues = { "Low level", "Normal level", "High level" }
You might try casting (Enum)(object)l, changing ToValueOfEnum to take an object, or just inline the method:
public static List<string> GetValuesOf<T>()
{
List<string> levelsToReturn = new List<string>();
var levels = Enum.GetValues(typeof(T)).Cast<T>();
foreach (T value in levels)
{
FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
ValueOfEnum[] attribs = fieldInfo.GetCustomAttributes(typeof(ValueOfEnum), false) as ValueOfEnum[];
levelsToReturn.Add(attribs.Length > 0 ? attribs[0].value : null);
}
return levelsToReturn;
}
Here's a one-line solution using the casting approach:
return new List<string>(Enum.GetValues(typeof(T)).Cast<Enum>().Select(x => x.ToValueOfEnum()));
In case you weren't clear on why T wasn't recognized as an Enum like E_Levels is, that's because you didn't specify that T : enum. Unfortunately, you can't specify that in C# (even though the CLR supports it), so other approaches like runtime checking/assuming (such as what I'm suggesting here) or post-compile code modifications (e.g. unconstrained-melody) have to be done.
.Net already has the same attribute Description so you can use this one instead ValueOfEnum.
What about dynamic and extension on type and following example
[TestFixture]
public sealed class ForTest
{
[Test]
public void Test()
{
var values = typeof(Levels).ToValues();
values.ForEach(Console.WriteLine);
}
}
public static class TypeExtensions
{
public static List<string> ToValues(this Type value)
{
var result = new List<string>();
var values = ToConcreteValues(value);
foreach (dynamic item in values)
{
Description attribute = GetAttribute<Description>(item);
result.Add(attribute.Description);
}
return result;
}
private static dynamic ToConcreteValues(Type enumType)
{
Array values = Enum.GetValues(enumType);
Type list = typeof (List<>);
Type resultType = list.MakeGenericType(enumType);
dynamic result = Activator.CreateInstance(resultType);
foreach (object value in values)
{
dynamic concreteValue = Enum.Parse(enumType, value.ToString());
result.Add(concreteValue);
}
return result;
}
private static TAttribute GetAttribute<TAttribute>(dynamic value)
where TAttribute : Attribute
{
Type type = value.GetType();
FieldInfo fieldInfo = type.GetField(Enum.GetName(type, value));
return (TAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof (TAttribute));
}
}
public enum Levels
{
[Description("Low level")]LOW,
[Description("Normal level")] NORMAL,
[Description("High level")] HIGH
}
result output:
Low level
Normal level
High level
All,
I'm trying to sort out my last bits in a Enum-framework.
My goal: I want to send any enum type and convert it to a List and bind it to a drop down list. i will use an ObjectDataSource as DataSource for the given drop down list. I want to create a composite control that only takes one parameter; enum type. The composite control will sort out databinding and all other bits and bops.
Now, the only problem I have is to convert the generic method to be compatible with the ObjectDataSource.
Here is the code for my current method that i need to use on my ObjectDataSource. So, this method is working fine and returns a list of items for the Enum type WeekDays. However, I need the same functionality, but I need to replace WeekDays with any type of enum.
Code:
public class DropDownData
{
public EnumDataItemList GetList()
{
EnumDataItemList items = new EnumDataItemList();
foreach (int value in Enum.GetValues(WeekDays))
{
EnumDataItem item = new EnumDataItem();
WeekDays d = (WeekDays)value;
//Set display text
if (!string.IsNullOrEmpty(DataHandlers.GetAttributeValue<DisplayTextAttribute, string>(d)))
{
//Translation logic goes here
item.Text = DataHandlers.GetAttributeValue<DisplayTextAttribute, string>(d);
}
else
{
//Translation logic goes here
item.Text = Enum.GetName(typeof(WeekDays), value);
}
item.Value = value; //Actual value
item.ToolTip = DataHandlers.GetAttributeValue<ToolTipAttribute, string>(d);
item.Description = DataHandlers.GetAttributeValue<Lia.Library.Enums.CustomAttributes.DescriptionAttribute, string>(d);
item.HelpText = DataHandlers.GetAttributeValue<HelpTextAttribute, string>(d);
item.ExcludeOnBinding = DataHandlers.GetAttributeValue<ExcludeOnBinding, bool>(d);
if (!item.ExcludeOnBinding)
{
items.Add(item);
}
}
return items;
}
}
public class EnumDataItemList : List<EnumDataItem>
{
}
As far as I know, I can't use a generic method with ObjectDataSOurce, but Generic Class is fine. I just can't get it to work with a generic class and all help is much appreciated. When all is working, I'll be happy to share the complete solution.
I'm using Framework 2.0.
This should help you. (Will throw Exception if T is not an enum type.)
public static EnumDataItemList GetList<T>() where T : struct
{
EnumDataItemList items = new EnumDataItemList();
foreach (int e in Enum.GetValues(typeof(T)))
{
EnumDataItem item = new EnumDataItem();
item.Text = Enum.GetName(typeof(T), e);
item.Value = e;
}
//Rest of code goes here
}
Usage:
EnumDataItemList days = GetList<WeekDays>();
if you don't want to use a generic method, you can change it to:
public static EnumDataItemList GetList(Type t)
{
EnumDataItemList items = new EnumDataItemList();
foreach (int e in Enum.GetValues(t))
{
EnumDataItem item = new EnumDataItem();
item.Text = Enum.GetName(t, e);
item.Value = e;
}
//Rest of code goes here
}
Alternative to Magnus', but the idea is pretty much exactly the same (just didn't want to throw it out after being beat to it ;-) ) - just iterates over the enum value rather than int. Same usage:
public static class DropDownData
{
// struct, IComparable, IFormattable, IConvertible is as close as we'll
// get to an Enum constraint. We don't actually use the constraint for
// anything except rudimentary compile-time type checking, though, so
// you may leave them out.
public static EnumDataItemList GetList<T>()
where T : struct, IComparable, IFormattable, IConvertible
{
// Just to make the intent explicit. Enum.GetValues will do the
// type check, if this is left out:
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Type must be an enumeration");
}
EnumDataItemList items = new EnumDataItemList();
foreach (Enum e in Enum.GetValues(typeof(T)))
{
EnumDataItem items = new EnumDataItem();
// Note: This assumes the enum's underlying type is
// assignable to Int32 (for example, not a long):
int value = Convert.ToInt32(e);
// The same attribute retrieval code as in the
// WeekDays example, including:
item.Text = e.ToString(); // e is Enum here, no need for GetName
}
}
}
I seem to have gone at this problem a little differently and came up with something fairly terse that appears to work for me. I cannot claim this as original work since I don't remember if I found it and copied it, or if I put it together from bits and pieces I found, with some original work of my own. I put an extension method on enums that gives me a ToDisplayText function for getting my custom enum attribute of the same name.
this.ddlBlah.DataSource =
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()
.ToDictionary(x => x, x => x.ToDisplayText());
this.ddlBlahs.DataValueField = "key";
this.ddlBlah.DataTextField = "value";
this.ddlBlah.DataBind();
public static string ToDisplayText(this Enum Value)
{
try
{
Type type = Value.GetType();
MemberInfo[] memInfo = type.GetMember(Value.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(
typeof(DisplayText),
false);
if (attrs != null && attrs.Length > 0)
return ((DisplayText)attrs[0]).DisplayedText;
}
}
catch (Exception ex)
{
throw new Exception("Your favorite error handling here");
}
return Value.ToString();
// End of ToDisplayText()
}
[System.AttributeUsage(System.AttributeTargets.Field)]
public class DisplayText : System.Attribute
{
public string DisplayedText;
public DisplayText(string displayText)
{
DisplayedText = displayText;
}
// End of DisplayText class definition
}
I've lots of enums in my app. Most of them are used on combos like this:
Enum.GetValues(typeof(TipoControlador))
Now I'd like to localize them like this: Localizing enum descriptions attributes
How can I combine them? My first thought was to override the ToString method with an extension method, but that's not possible =(
Using the other article as a basis, you can create an extension method like this:
public static class LocalizedEnumExtensions
{
private static ResourceManager _resources = new ResourceManager("MyClass.myResources",
System.Reflection.Assembly.GetExecutingAssembly());
public static IEnumerable<string> GetLocalizedNames(this IEnumerable enumValues)
{
foreach(var e in enumValues)
{
string localizedDescription = _resources.GetString(String.Format("{0}.{1}", e.GetType(), e));
if(String.IsNullOrEmpty(localizedDescription))
{
yield return e.ToString();
}
else
{
yield return localizedDescription;
}
}
}
}
You would use it like this:
Enum.GetValues(typeof(TipoControlador)).GetLocalizedNames();
Technically, this extension method will accept any array, and you can't restrict it to only work on an enum, but you could add extra validation inside the extension method if you feel it's important:
if(!e.GetType().IsEnum) throw new InvalidOperationException(String.Format("{0} is not a valid Enum!", e.GetType()));
You have 2 problems here, the first is how to localize enums which is solved by Localizing enum descriptions attributes.
The second is how to display the localized name whilst using the enum's value. This can be solved by creating a simple wrapper object such as:
public sealed class NamedItem
{
private readonly string name;
private readonly object value;
public NamedItem (string name, object value)
{
this.name = name;
this.value = value;
}
public string Name { get { return name; } }
public object Value { get { return value; } }
public override string ToString ()
{
return name;
}
}
This provides a generic re-usable class for any drop down box where you might want to show a different name for an item than the item itself provides (eg enums, ints, etc).
Once you have this class, you can set the drop down's DisplayMember to Name and ValueMember to Value. This will mean that dropdown.SelectedValue will still return your enum.
I know this question is old, but this may help some people.
You can just handle the Format event of the ComboBox control (http://msdn.microsoft.com/en-us/library/system.windows.forms.listcontrol.format.aspx), and add your text logic in it.
private void ComboBoxFormat(object sender, ListControlConvertEventArgs e)
{
e.Value = GetDescription(e.Value);
}
public static string GetDescription(object item)
{
string desc = null;
Type type = item.GetType();
MemberInfo[] memInfo = type.GetMember(item.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
desc = (attrs[0] as DescriptionAttribute).Description;
}
}
if (desc == null) // Description not found
{
desc = item.ToString();
}
return desc;
}
With this, the ComboBox control still holds enum values rather than strings.
I have an enumeration for my Things like so:
public enum Things
{
OneThing,
AnotherThing
}
I would like to write an extension method for this enumeration (similar to Prise's answer here) but while that method works on an instance of the enumeration, ala
Things thing; var list = thing.ToSelectList();
I would like it to work on the actual enumeration instead:
var list = Things.ToSelectList();
I could just do
var list = default(Things).ToSelectList();
But I don't like the look of that :)
I have gotten closer with the following extension method:
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;
}
}
Used like so:
var list = typeof(Things).ToSelectList();
Can we do any better than that?
Extension methods only work on instances, so it can't be done, but with some well-chosen class/method names and generics, you can produce a result that looks just as good:
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;
}
}
Then you can get your select list like this:
var list = SelectList.Of<Things>();
IMO this reads a lot better than Things.ToSelectList().
No.
The best you can do is put it on a static class, like this:
public static class ThingsUtils {
public static SelectList ToSelectList() { ... }
}
Aaronaught's answer is really great, based on that I made the following implementation:
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.");
}
}
In my opinion it's a little bit safer, as you can - almost - call it only with Enums, and of course instead of the throw you can simply return null if you want an exception-free version.
I use 'Type' instead of 'Enum' to add extension. Then I can get any type of list back from the method. Here it returns string values:
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();
}
Later I could use this syntax to get what I want:
var listOfThings = typeof (Things).AllDescription();
#Aaronaught has a very good answer. To extend his answer, you can also even make it more generic. I have this in a global library...
public static IQueryable GetAllEnumValues<T>()
{
IQueryable retVal = null;
Type targetType = typeof(T);
if(targetType.IsEnum)
{
retVal = Enum.GetValues(targetType).AsQueryable();
}
return retVal;
}
Now you have de-coupled this functionality from the SelectList class. So you can call this in your SelectList methods, or anywhere else for that matter.
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");
}
}
In my opinion, this is the cleanest way. Why?
It works for any System.Enum
The extension method itself is cleaner.
To call it you just add new and that's a small trade off (because it has to have an instance in order to work.
You aren't passing null around and it literally won't compile if you try to use it with another type.
Usage:
(new Things()).ToSelectList()
Extension Method:
[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");
}
The closest you can come, I think, is to dummy things up a bit to work like an enum without being one. Here's what I've come up with--it seems like a lot of work just to plop a static method on an enumeration, although I do understand the programming appeal of it:
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;
}
}
}