Splitting a FLAGS enum into its individual enumerated values

K

Ken Durden

Any ideas on what the best way to do this is:

[Flags]
public enum EOptions
{
op1 = 0x01,
op2 = 0x02,
op3 = 0x04,
op4 = 0x08,
op5 = 0x10,
op6 = 0x20,
op7 = 0x40,
op8 = 0x80,
}

public void F()
{
EOptions e = EOptions.op1 | EOptions.op3 | EOptions.op7;

EOptions[] opArray = Magic( e );
opArray.Length == 3;
opArray.Contains( EOptions.op1 );
opArray.Contains( EOptions.op3 );
opArray.Contains( EOptions.op7 );
}

How should I write Magic, to work with any enumerated type? I think we
can assume that the enum values represent individual bits selected as
high or low, as it is a FLAGS enum.

Thx,
-ken
 
N

Nicholas Paldino [.NET/C# MVP]

Ken,

Here is how I would do it:

public static Array SplitFlagEnumerationValue(Type enumType, object value)
{
// Create an array list which will hold the values.
ArrayList pobjValues = new ArrayList();

// Cycle through the values in the enumeration.
foreach (object pobjValue in Enum.GetValues(enumType))
// Cast to long. When masked, if the value is non zero, then
// the value in the enumeration is valid.
if ((((long) pobjValue) & ((long) value)) <> 0)
// Add the element to the array.
pobjValues.Add(pobjValue);

// Create the return value.
Array pobjRetVal = Array.CreateInstance(enumType, pobjValues.Count);

// Copy to the return value.
pobjValues.CopyTo(pobjRetVal);

// Create a typed copy of the array.
return pobjRetVal;
}

I chose to cast to long in the event that the enumeration was based on a
long.

Hope this helps.
 
K

Ken Durden

Nicholas Paldino said:
Ken,

Here is how I would do it:

public static Array SplitFlagEnumerationValue(Type enumType, object value)
{
// Create an array list which will hold the values.
ArrayList pobjValues = new ArrayList();

// Cycle through the values in the enumeration.
foreach (object pobjValue in Enum.GetValues(enumType))
// Cast to long. When masked, if the value is non zero, then
// the value in the enumeration is valid.
if ((((long) pobjValue) & ((long) value)) <> 0)
// Add the element to the array.
pobjValues.Add(pobjValue);

// Create the return value.
Array pobjRetVal = Array.CreateInstance(enumType, pobjValues.Count);

// Copy to the return value.
pobjValues.CopyTo(pobjRetVal);

// Create a typed copy of the array.
return pobjRetVal;
}

I chose to cast to long in the event that the enumeration was based on a
long.

Hope this helps.

Nicholas,

Your example only works if the only enumerated values in the
enumerated type are individual values; sometimes, for convenient
client-side usage, the enum values are merged together as part of the
definition:

Ex:
[Flags]
private enum EColor
{
Red = 0x1, // This one is simple
Green = 0x2, // This one is also simple
Blue = 0x4, // This one is also simple

RedGreen = Red | Green, // This one is composite
BlueGreen = Blue | Green // This one is also composite
}

I have some similar code, however, that simply checks whether the
value is a power of 2 or not, which indicates whether its a composite
value or a singular value.

public static bool IsCompositeValue( Enum eValue )
{
object ob = (object) eValue;
long n = (long) ob;
return ATMath.IsPower2( n );
}

When I execute this, however, I get a "specified cast is not valid"
exception on the line where I'm casting into a long. It seems like
your code would run into the same issue, did you actually run it? If
your code runs w/o exceptions, why doesn't mine?

Thx,
-ken
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top