Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# execute all cases in switch statement

I have a switch statement like the following :

switch(task)
    {
        case 1:
            print();
            break;
        case 2:
            save();
            break;
        case 3:
            sendmail();
            break;
    }

I need a way to execute all cases, which means if task is (All) I want to print, save and send mail. Is it doable using some modification on the given case I know that, I can make it as follow:

case All:
    print();
    save();
    sendmail();
    break;

But as I said I want to know, if there is a way in switch statement to execute all cases. Thanks in advance

like image 361
RMohammed Avatar asked Sep 17 '15 09:09

RMohammed


1 Answers

To answer your actual question:

if there is a way in switch statement to execute all cases.

Not a clean way that I can think of.


I would suggest changing the pattern a bit and instead making task a flag enum

[Flags]
public enum TaskOptions 
{
    Print    = 1,
    Save     = 2,
    SendMail = 4,
    //Note that these numbers go up in powers of two
}

You can then do something like the following:

task = TaskOptions.Print | TaskOptions.Save;
if (task.HasFlag(TaskOptions.Print))
{ 
    print();
}
if (task.HasFlag(TaskOptions.Save))
{ 
    save();
}
if (task.HasFlag(TaskOptions.SendMail))
{ 
    sendMail();
}

You no longer have to worry explicitly about all


Then if you wanted to add a new option

[Flags]
public enum TaskOptions 
{
    Print    = 1,
    Save     = 2,
    SendMail = 4,
    NewOption = 8,
}

task = TaskOptions.Print | TaskOptions.Save;
if (task.HasFlag(TaskOptions.Print))
{ 
    print();
}
if (task.HasFlag(TaskOptions.Save))
{ 
    save();
}
if (task.HasFlag(TaskOptions.SendMail))
{ 
    sendMail();
}
if (task.HasFlag(TaskOptions.NewOption))
{ 
    newOption();
}

Jaymee asked for clarification about the | and the &

Can you please explain the syntax of task = TaskOptions.Print | TaskOptions.Save. Not sure on the use of the pipe here, I thought it was 'or', but there's no evaluation here!? In fact, same for the single ampersand - never seen it used in that way before

These are bitwise operators. They compare two numbers, bit by bit and return a result.

In our example, we're using 4 flags, each represented by a boolean. A boolean can be represented by one bit.

Let's use the following abbreviations:

Print = P
Save = S
SendMail = M
NewOption = N

8  4  2  1
N  M  S  P

I used task = TaskOptions.Print | TaskOptions.Save as an example

0  0  0  1   P is declared as 1 in the enum. 
0  0  1  0   S is declared as 2 in the enum.
========== 
0  0  1  1   < I've "or'd" these numbers together. They now represent Print AND Save as one option. The number "3" (binary 0011) is equivalent to "print and save"

When I have "3" and I want to know if it contains a specific flag, I & with that flag.

N  M  S  P
0  0  1  1  //This is P & S
0  0  0  1  //And we want to check if it has "P"
==========
0  0  0  1  < this returns non-zero. it contains the flag!

Let's do the same thing for N

N  M  S  P
0  0  1  1  //This is P & S
1  0  0  0  //And we want to check if it has "N"
==========
0  0  0  0  < this returns zero. This state doesn't contain "N"

Edit by David Arno

To add to this answer, rather than having a series of ifs, a Dictionary and for loop can be used instead:

private readonly Dictionary<TaskOptions, Action> actions =
    new Dictionary<TaskOptions, Action>
    {
        { TaskOptions.Print, Print },
        { TaskOptions.Save, Save },
        { TaskOptions.SendMail , SendMail }
    };

...

var task = TaskOptions.Print | TaskOptions.Save;
foreach (var enumValue in Enum.GetValues(typeof(TaskOptions)).Cast<TaskOptions>())
{
    if (task.HasFlag(enumValue))
    {
        actions[enumValue]();
    }
}
like image 60
James Webster Avatar answered Sep 19 '22 16:09

James Webster