Switch on Enum (with Flags attribute) without declaring every possible combination?

后端 未结 9 2120
忘掉有多难
忘掉有多难 2021-01-31 14:15

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

9条回答
  •  耶瑟儿~
    2021-01-31 14:45

    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
    }
    

提交回复
热议问题