2

Is it possible to check a condition is true for each line of a statement block without having if (condition) before each line?

For example:

if (condition)
{
    DoSomething();
    DoSomethingElse();
    DoAnotherThing();
}

At some point another background process may have set condition to false before DoSomethingElse() has been executed. Essentially I'm look for an efficient and easier way of saying:

if (condition) DoSomething();
if (condition) DoSomethingElse();
if (condition) DoAnotherThing();

In reality it's a long block of code, executed once, that I want to abandon if at any point a particular flag is changed.

What is the best way to tighten up this kind of code.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
iajs
  • 167
  • 4
  • 14
  • 2
    Polymorphism. Create classes that represent the entities DoSomething(), DoSomethingElse() and DoAnotherThing(). Then call myclass1.doThing(); myclass2.doThing(), and myclass3.doThing(). Inside those methods are a redirect to a single method which checks for condition, then runs the appropriate function. http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism – Eric Leschinski Aug 29 '13 at 14:47
  • If, Else IF, Else If, Else...? – JsonStatham Aug 29 '13 at 14:47

7 Answers7

7

No - the condition will be checked once and then the entire block executed. Another option might be to inject bailouts in the block:

if (condition)
{
    DoSomething();
    if(!condition) return;
    DoSomethingElse();
    if(!condition) return;
    DoAnotherThing();
}

Another way is if the functions could be parameterized so that you could put them in a loop:

foreach (varmyParam in parameters)
{
    if(condition)
       DoSomething(myParam);
}

Edit

After thinking a bit more this may be your best option:

List<Action> funcs = new List<Action> {DoSomething, DoSomethingElse, DoAnotherThing};
foreach( Action a in funcs)
{
   if(condition) a();
}

That requires that all of the methods have the same signature (in your case return void with no parameters) but it's a bit cleaner.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • That's a much better alternative than checking each line, and I think it's what I'm going to have to go with! – iajs Aug 29 '13 at 14:49
  • How in the world do you use break from an if statement like that? – Moop Aug 29 '13 at 14:53
  • Return might not work as well, since the code block might not be in a method. – Moop Aug 29 '13 at 15:00
  • you could also do `var funcs = new[]{ ... }`, which is much shorter (no reason to box them in a `List` when they are only used in the foreach) – default Aug 29 '13 at 15:19
1

Encapsulate the check, perhaps?

if(condition)
    DoSomething(condition);

and inside DoSomething

if(condition)
{
    // do your stuff inside method.
}

Meaning your code now looks like:

DoSomething(condition);
DoSomethingElse(condition);
christopher
  • 26,815
  • 5
  • 55
  • 89
  • IMO, that doesn't work well with the method name thought. If I execute `DoSomething` I expect it to do.. something. Not nothing. It would also just be moving the problem. – default Aug 29 '13 at 15:21
  • It would be; you're correct. But OP was trying to clear up that code. By propagating three if statements in one block to one if statement in three blocks, it definitely looks a lot cleaner. Agreed on the method name though. – christopher Aug 29 '13 at 15:55
0

You could throw wrap it in a try/catch block and throw an exception inside each method when a flag is changed:

try 
{
    DoSomething();
    DoSomethingElse();
    DoAnotherThing();
}
catch (FlagChangedException e)
{
    // do something to handle it
}
zigdawgydawg
  • 2,046
  • 13
  • 10
0

Maybe like this:

int step = 1;
bool running = true;

while (running && condition) {
   switch (step) {
      case 1: DoSomething(); break;
      case 2: DoSomethingElse(); break;
      case 3: DoAnotherThing(); break;
      // and maybe other cases
      default: running = false; break; // AFAIK you can't break out of both switch and while (without labels)
   }

   step = step + 1;
}
Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
0

You could wrap it in a delegate method call the method with your condition and the method you want to execute if it's true. You could even do it with a list of functions:

void Main()
{
   DoSomething();
   DoIf(true, DoWork1);
   DoIf(false, DoWork2);
   var MyFunctions = new List<MyFunction>() { DoWork1, DoWork2 };

   foreach(var func in MyFunctions) {
       DoIf(someBoolCondition == 0, func);
   }
}

public delegate void MyFunction();

void DoSomething() {
   Console.WriteLine("Always");
}

public void DoWork1() {
    Console.WriteLine("Only if it was true");
}

public void DoWork2() {
   Console.WriteLine("Only if it was true");
}

void DoIf(bool condition, MyFunction function) {
   if(condition) {
       function();
   }
}

Outputs:

Always
Only if it was true
xdumaine
  • 10,096
  • 6
  • 62
  • 103
0

You could use a lambda with an Action but this doesn't really save much typing:

Action<Action> exec = a => { if (condition) a(); };

exec(DoSomething);
exec(DoSomethingElse);
exec(DoAnotherThing);
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
-1

It sounds like you're using multiple threads - one thread to do the work and some other thread that can cancel the request to do work.

If that's the case, you should consider just aborting the thread doing the work vs setting some flag. Check out http://msdn.microsoft.com/en-us/library/System.Threading.Thread.Abort.aspx

It's pretty simple and keeps the flag checking out of your worker thread.

One big assumption with Thread.Abort is that it's safe to abort your worker method(s) in the middle of a task. Your current solution of flag checking allows the currently executing method to complete before it abandons the rest of the work - so just keep that in mind.

Mike Pugh
  • 6,787
  • 2
  • 27
  • 25
  • I would strongly urge not to use thread.abort for something this simple. http://stackoverflow.com/questions/421389/is-this-thread-abort-normal-and-safe – Moop Aug 29 '13 at 15:38
  • We don't know how simple it is - the OP is just a dummy example but refers to a much larger block of code. – Mike Pugh Aug 29 '13 at 15:40
  • @Moop - your reference shows a particularly bad scenario for Thread.Abort but I wouldn't let that dictate avoiding Thread.Abort for everything... – Mike Pugh Aug 29 '13 at 15:48