Hanu
Hanu

Reputation: 11

How to validate multiple or conditions for an If statement for Enums in C#?

I have an enum class named AccountStatus with nearly 20 enum values. And I need to perform some operation if 10 enums are matched. and perform another operation if remain enums matched. Now My I have written code as follows

public enum AccountStatus
{
Unknown ,
Pending,
Deleted,
Declined,
Deactivated,
Processing,
......
}

My Sample if condition is

if(status == AccountStatus.Unknown || status == AccountStatus.Pending || status == AccountStatus.Declined 
 ||status == AccountStatus.Hold|| status == AccountStatus.Stopped|| status == AccountStatus.Deferred
 ||status == AccountStatus.Rejected || status == AccountStatus.Waiting|| status == AccountStatus.Deleted)
{
   // Perform Some operation.
}

Is there a better way to avoid those many or conditions?

Upvotes: 0

Views: 1006

Answers (3)

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

The answer of Max Play, with the big Switch Case statement is good in its simplicity. However, it is impossible to work with it, if you do have a lot of enums. It is also very difficult to unit test it, to make sure that you haven't forgotten a case

If seems to me, that if the AccountStatus is Unknown / Pending / Declined / Waiting / etc. there is something common about the status. This common thing makes that you want to process Accounts with these statusses differently: there are two "groups of accounts"

Consider to number your enums strategically, making it fields.

I don't know what is so special about these AccountTypes that they need to be treated differently. Therefore I'll have to give an example with an enum of Car types.

[Flage]
enum CarType
{
    None = 0x00,
    Gaz = 0x01,
    Electric = 0x02,
    FourWheelDrive = 0x04
    AirConditioning = 0x08,
    SunRoof = 0x10,
    CruiseControl = 0x20,
    ... // etc

    BMW1Series      = Gaz,
    BMW4Series      = Gaz | AirConditioning,
    BMW4x4          = Gaz | FourWheelDrive,
    BMW4x4Executive = Gaz | FourWheelDrive | AirConditioning | CruiseControl,

    TotoyataPrius    = Gaz | Electric | Airconditioning | CruiseControl,
    ...

Now to know if a Car needs to have its Airconditioning serviced during its regular maintenance, you could do the big switch case where you have all known models of Cars:

bool NeedsAirconditioningCheck(Car car)
{
   switch (car.CarType)
   {
       case ToyotaPrius:
       case BMW4x4Executive:
       ...
       // etc, do this for all 1254 car models that have an airconditioning
          return true;

       default:
           return false;
}

Using Flags, this would be way more easier:

bool NeedsAirconditioningCheck(Car car)
{
    return (car.CarType & CarType.AirConditioning) == CarType.AirConditioning;
}

Another example: a Car is Hybrid if it uses Gaz and Electricity:

bool IsHybrid(Car car)
{
    CarType Hybrid = CarType.Gaz | Cartype.Electric;
    return (car.Cartype & Hybrid) == Hybrid;
}

Advantages:

  • These procedures won't have to change, if your enum is extended with new Car models
  • These procedures won't have to change if we invent a new feature. For instance, if a new feature like KeepYourLane is invented, then apparently all existing car models didn't have this feature. All old CarTypes won't have to change, only the newly added ones.
  • Way more easier to understand, and to visually check if the method is correct
  • Easier to unit test

Upvotes: 0

TheHvidsten
TheHvidsten

Reputation: 4428

If your enum checks always checks for these values you could put them in the order you want them. An enum is really just an int value, and you can assign int values to them as you see fit. As such, you can also compare an enum to an int.`

public enum AccountStatus {
  Unknown = 0,
  Pending = 1,
  Declined = 2
  // and so on
}

The values I set there are the same as default values, but you can see how you can use other values instead of the default ones.

Then you just compare as you would normally:


public static void Main() {
  AccountStatus s = AccountStatus.Pending;

  if (s <= AccountStatus.Pending) {
    // Perform some operation
  } else {
    // Perform some other operation
  }
}

Upvotes: 1

Max Play
Max Play

Reputation: 4037

A possible solution would be to change the check into a switch operation:

switch (status)
{
    case AccountStatus.Unknown:
    case AccountStatus.Pending:
    case AccountStatus.Declined:
    case AccountStatus.Hold:
    case AccountStatus.Stopped:
    case AccountStatus.Deferred:
    case AccountStatus.Rejected:
    case AccountStatus.Waiting:
    case AccountStatus.Deleted:
    {
       // Perform Some operation.
    }
    break;
}

Upvotes: 3

Related Questions