how do i switch on an enum which have the flags attribute set (or more precisely is used for bit operations) ?
I want to be able to hit all cases in a switch that matche
What about a Dictionary<CheckType,Action> that you will fill like
dict.Add(CheckType.Form, DoSomething);
dict.Add(CheckType.TempDate, DoSomethingElse);
...
a decomposition of your value
flags = Enum.GetValues(typeof(CheckType)).Where(e => (value & (CheckType)e) == (CheckType)e).Cast<CheckType>();
and then
foreach (var flag in flags)
{
if (dict.ContainsKey(flag)) dict[flag]();
}
(code untested)
The easiest way is to just perform an ORed enum, in your case you could do the following :
[Flags()]public enum CheckType
{
Form = 1,
QueryString = 2,
TempData = 4,
FormQueryString = Form | QueryString,
QueryStringTempData = QueryString | TempData,
All = FormQueryString | TempData
}
Once you have the enum setup its now easy to perform your switch statement.
E.g, if i have set the following :
var chkType = CheckType.Form | CheckType.QueryString;
I can use the following switch statement as follows :
switch(chkType){
case CheckType.Form:
// Have Form
break;
case CheckType.QueryString:
// Have QueryString
break;
case CheckType.TempData:
// Have TempData
break;
case CheckType.FormQueryString:
// Have both Form and QueryString
break;
case CheckType.QueryStringTempData:
// Have both QueryString and TempData
break;
case CheckType.All:
// All bit options are set
break;
}
Much cleaner and you don't need to use an if statement with HasFlag. You can make any combinations you want and then make the switch statement easy to read.
I would recommend breaking apart your enums, try see if you are not mixing different things into the same enum. You could setup multiple enums to reduce the number of cases.
Flags enums can be treated as a simple integral type in which each individual bit corresponds to one of the flagged values. You can exploit this property to convert the bit-flagged enum value into an array of booleans, and then dispatch the methods you care about from a correlated array of delegates.
EDIT: We could certainly make this code more compact through the use of LINQ and some helper functions, but I think it's easier to understand in the less sophisticated form. This may be case where maintainability trumps elegance.
Here's an example:
[Flags()]public enum CheckType
{
Form = 1,
QueryString = 2,
TempData = 4,
}
void PerformActions( CheckType c )
{
// array of bits set in the parameter {c}
bool[] actionMask = { false, false, false };
// array of delegates to the corresponding actions we can invoke...
Action availableActions = { DoSomething, DoSomethingElse, DoAnotherThing };
// disassemble the flags into a array of booleans
for( int i = 0; i < actionMask.Length; i++ )
actionMask[i] = (c & (1 << i)) != 0;
// for each set flag, dispatch the corresponding action method
for( int actionIndex = 0; actionIndex < actionMask.Length; actionIndex++ )
{
if( actionMask[actionIndex])
availableActions[actionIndex](); // invoke the corresponding action
}
}
Alternatively, if the order in which you evaluate doesn't matter, here is simpler, clearer solution that works just as well. If order does matter, replace the bit-shifting operations with an array containing the flags in the order you want to evaluate them in:
int flagMask = 1 << 31; // start with high-order bit...
while( flagMask != 0 ) // loop terminates once all flags have been compared
{
// switch on only a single bit...
switch( theCheckType & flagMask )
{
case CheckType.Form:
DoSomething(/*Some type of collection is passed */);
break;
case CheckType.QueryString:
DoSomethingElse(/*Some other type of collection is passed */);
break;
case CheckType.TempData
DoWhatever(/*Some different type of collection is passed */);
break;
}
flagMask >>= 1; // bit-shift the flag value one bit to the right
}
How about this. Of course the arguments and return types of DoSomething, etc., can be anything you like.
class Program
{
[Flags]
public enum CheckType
{
Form = 1,
QueryString = 2,
TempData = 4,
}
private static bool DoSomething(IEnumerable cln)
{
Console.WriteLine("DoSomething");
return true;
}
private static bool DoSomethingElse(IEnumerable cln)
{
Console.WriteLine("DoSomethingElse");
return true;
}
private static bool DoWhatever(IEnumerable cln)
{
Console.WriteLine("DoWhatever");
return true;
}
static void Main(string[] args)
{
var theCheckType = CheckType.QueryString | CheckType.TempData;
var checkTypeValues = Enum.GetValues(typeof(CheckType));
foreach (CheckType value in checkTypeValues)
{
if ((theCheckType & value) == value)
{
switch (value)
{
case CheckType.Form:
DoSomething(null);
break;
case CheckType.QueryString:
DoSomethingElse(null);
break;
case CheckType.TempData:
DoWhatever(null);
break;
}
}
}
}
}
Cast it to its base type, the great thing about this is it tells you when there are duplicate values present.
[Flags]
public enum BuildingBlocks_Property_Reflection_Filters
{
None=0,
Default=2,
BackingField=4,
StringAssignment=8,
Base=16,
External=32,
List=64,
Local=128,
}
switch ((int)incomingFilter)
{
case (int)PropFilter.Default:
break;
case (int)PropFilter.BackingField:
break;
case (int)PropFilter.StringAssignment:
break;
case (int)PropFilter.Base:
break;
case (int)PropFilter.External:
break;
case (int)PropFilter.List:
break;
case (int)PropFilter.Local:
break;
case (int)(PropFilter.Local | PropFilter.Default):
break;
}
Just use HasFlag
if(theCheckType.HasFlag(CheckType.Form)) DoSomething(...);
if(theCheckType.HasFlag(CheckType.QueryString)) DoSomethingElse(...);
if(theCheckType.HasFlag(CheckType.TempData)) DoWhatever(...);