开发者

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&lt;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();
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜