Bitfield enum extension method to return dictionary of included values
Enums can sure be confusing. I am trying to create an extension method on the Enum type that will take a value and return the names of all the bits that match.
Given:
[Flags]
public enum PlanetsEnum
{
Mercury=1,
Venus=2,
Earth=4,
Mars=8,
Jupiter=16,
//etc....
}
I would like to create an extension method that return a dictionary of only the selected values. So if:
PlanetsEnum neighbors = PlanetsEnum.Mars | PlanetEnum.Venus; //10
IDictionary dict = neighbors.ToDictionary();
foreach (KeyValuePair<String, Int32> kvp in dict)
{
Console.WriteLine(kvp.Key);
}
/*
* Should Print:
* Mars
* Venus
*/
I would expect to see Mars & Venus written to the console but I am instead seeing all the values of PlanetEnum. Here is my extension method code:
public static IDictionary<string, Int32> ToDictionary(this Enum enumeration)
{
Type type = enumeration.GetType();
return Enum.GetValues(type).Cast<Int32>().ToDictionary(field => Enum.GetName(type, field));
}
Does anyone see what I开发者_JS百科 am doing wrong? I know that Enum.GetValues
is returning all fields of the enum type, how do I get it to only return fields of the enum instance?
Thanks a lot for any help,
Keith
Here's the LINQ-ified version of what you're trying to do. The key bit you're missing is checking the current value:
public static IDictionary<string, int> ToDictionary(this Enum enumeration)
{
int value = (int)(object)enumeration;
return Enum.GetValues(enumeration.GetType()).OfType<int>().Where(v => (v & value) == value).ToDictionary(v => Enum.GetName(enumeration.GetType(), v));
}
Edit:
A little explanation on why we do the (int)(object)enumeration
cast:
Bitwise operators only work against integral types (like int) and boolean, but Enum is not directly cast-able to int. So we must downcast to an object and presume that it actually represents an int as the underlying type - the compiler will allow us to cast an object to an int. If the enumeration is not integer-based, this will throw a runtime exception.
Try the following. It only works for Enum's which are int32's
public static IDictionary<String, Int32> ToDictionary(this Enum enumeration)
{
var map = new Dictionary<string, int>();
var value = (int)(object)enumeration;
var type = enumeration.GetType();
foreach (int cur in Enum.GetValues(type))
{
if (0 != (cur & value))
{
map.Add(Enum.GetName(type, cur),cur);
}
}
return map;
}
public enum CustomerType
{
Standard = 0,
Trade = 1
}
ddCustomerTypes.DataSource = (new Domain.CustomerType()).ToDictionary();
ddCustomerTypes.DataBind();
public static class EnumExtensionMethods
{
public static Dictionary<string, object> ToDictionary(this Enum enumeration)
{
Array names = Enum.GetNames(enumeration.GetType());
Dictionary<string, object> dictionary = new Dictionary<string, object>();
foreach (string name in names)
{
dictionary.Add(name, typeof(Domain.CustomerType).GetField(name).GetRawConstantValue() );
}
return dictionary;
}
public static List<KeyValuePair<string, object>> ToList(this Enum enumObject)
{
return enumObject.ToDictionary().ToList();
}
}
精彩评论