I have various enums that I use as sources for dropdown lists, In order to provide for a user-friendly description, I added a Description
attribute to each enum, and then do the following:
var list = Enum.GetValues(typeof(MyEnum))
.Cast<MyEnum>()
.ToDictionary(k => k, v => v.GetAttributeOfType<DescriptionAttribute>().Description)
.ToList();
The above is repetitive because I have to use it in a lot of places. I tried to add an extension method:
public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return (attributes.Length > 0) ? (T)attributes[0] : null;
}
public static KeyValuePair<T, string> ToList<T>(this Enum source)
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(k => k, v => v.GetAttributeOfType<DescriptionAttribute>().Description)
.ToList();
}
However, I get an exception:
Cannot convert lambda expression to type 'System.Collections.Generic.IEqualityComparer' because it is not a delegate type
What is the correct way to use it as an extension (using the above 2 methods)?
There is no correct way to use it as an extension. Extension methods (similar to instance methods) are used when you have a value (instance) and for instance want to get some information related to that value. So the extension method would make sense if you want to get the description of a single
enum
value.However, in your case the information you need (the list of
enum
value/description pairs) is not tied to a specificenum
value, but to theenum
type. Which means you just need a plain static generic method similar toEnum.TryParse<TEnum>
. Ideally you would constrain the generic argument to allow onlyenum
, but this type of constraint is not supported (yet), so we'll use (similar to the above system method) justwhere TEnum : struct
and will add runtime check.So here is a sample implementation:
and usage:
Whenever I need an enumeration (a static list of known values) that need to have something more than just a mere integer value and a string counterpart, I end up using this Enumeration Utility class that essentially gives me java-like enumeration behavior.
So that would be my first option if I were on op's shoes as it would make it really trivial to achieve what he/she wants.
But, assuming this is not an option for op and she/he need to stick with C# enums, I would use a combination of both ehsan-sajjad and frank-j solutions:
Here is how I would implement this:
And here is what the usage would look like:
I have this extension method in my stack and use it for the same thing all the time.
Example usage:
Additionally, you can use this one to get a IDictionary for binding purposes.
Use it like so:
Update
Here is a working .NET Fiddle.
Then use it like this:
You can create a generic method which would take
Enum
andAttribute
as generic argument.For getting any attribute, you can create an extension method like:
and here is the method for converting it to dictionary:
You can call it this way:
I have used this Enum and Attribute as example:
Output:
Another take on this:
Try replacing
with
In your example, the wrong overload of ToDictionary() is being called.