views:

313

answers:

10

Hi guys.

In Delphi I could do something like this:

try
  if not DoSomething then
    Exit;
  if not DoSomething2 then
    Exit;
  if not DoSomething3 then
    Exit;

finally
  DoSomethingElse;
end;

In other means if method DoSomething results false then the program flow is transffered to the finally block and DoSomething2 and DoSomething3 are not executed.

How to achieve such behaviour in C#?

Thanks in advance.

Edit1: The below example doesn't compile in VS 2008

Edit2: I am sorry I was to fast and forget the return statement;

XElement OrderStatus(q_order_status Request)
{
  XElement Response;
  try
  { 
    if (DoSomething() != 0 )
    {
      return;
    }
  }
  catch(Exception e)
  {
    // catch some errors and eventually pass the e.Message to the Response
  }
  finally
  {
    Response =  new XElement("SomeTag", "SomeResponse");
  }
  return Response;
}

Edit3: After testing it seems that the easiest way to achieve this is to throw an exception if the result of DoSomething1 is false. I can throw my own execption, write a specific message and pass it to the finally clause.

+14  A: 

You really shouldn't be using exception handling constructs for flow control. That said, Exit is comparable to return in C#. As the MSDN Documentation about the [return keyword][1] says:

If the return statement is inside a try block, the finally block, if one exists, will be executed before control returns to the calling method.

In general a finally-block will almost always execute if the corresponding try-block has been reached. There are a few rare situations where it is impossible to guarantee that the finally-block executes, but they are all fatal errors, upon which programs should likely immediately crash.

How your code would look in C#:

try
{
    if (!DoSomething())
        return;

    if (!DoSomething2())
        return;

    if (!DoSomething3())
        return;
}
finally
{
    DoSomethingElse();
}

But again, don't do this. try and finally are intended for handling exceptions, not for normal flow control.

Reply to your edit:
In your code return doesn't compile because the return type of the method is XElement and return by itself can only be used when the return type is void. You could use return new XElement("SomeTag", "SomeResponse");, as that is what the finally would be doing anyway, or you could assign Response earlier and do return Response;.

Note though that while the finally always executes, the return Response; that comes after it doesn't execute if the reason went into the finally-block is because you did a return inside the try-block.

Joren
I strongly disagree with you but that was not my question. Also Exit and return behaviour is not identical in those languages so that gives me nothing.
Wodzu
Joren thanks return in such way doesn't compile.
Wodzu
I think you're replying to my answer just before the edit? My updated answer does give the behaviour you were looking for. If a return statement is in a try-block with a finally block, the finally block will be executed before the method ends. But it's still very much wrong to use try-finally for non-exceptional flow control.
Joren
My code does compile. What exactly is the code you're trying, and what error do you get?
Joren
I dont think this answer the users question, if any of the *DoSomething* functions return false, the *DoSomethingElse* is executed and not any of the other DoSomethings. I may be wrong, but a *return* doesnt bring the flow into the *finally* block, correct? Also, encourage the correct usage of try/catch/finally versus if/else blocks.
mizipzor
@Joren: _Exceptions_ aren't meant for normal flow control. try/finally are perfectly good tools for flow control. .NET Exception handling is optimized so that throwing/catching an exception is expensive, but setting up a catch/finally handler is not. In fact, every C# programmer (should) be using finally all the time in its disguises "using" and "lock".
nikie
Thanks Joren. I really don't want to discuss is this a good programming technique or bad. I just want to focus on the solution, we may discuss the other thing privately :)
Wodzu
@mizipor: Quote from C# Language reference: "The finally block is useful for cleaning up any resources allocated in the try block as well as running any code that must execute even if there is an exception. Control is always passed to the finally block regardless of how the try block exits."
nikie
I've updated my answer to be more explicit about the execution of the finally block.
Joren
Joren could you take a look at the updaten question.
Wodzu
@nikie: I stand corrected, thank you.
mizipzor
Jason: in response to your reply: The problem is that I want include in Response a possible exception message and that was guaranted by the finally block.
Wodzu
If response is an object then the object can be modified in the finally block, even if you can't return a different response object reference.
JonB
+2  A: 

Why not make the three try-lines a common if/else block? Instead of exit, call the DoSomethingElse. Like so:

if (DoSomething() == false)
{ 
 DoSomethingElse();
}
else if (DoSomething2() == false)
{
 DoSomethingElse();
}
else if (DoSomething3() == false)
{
 DoSomethingElse();
}

I would like to say that "C# is not Delphi", but that would be a bit arrogant.

mizipzor
+1 For giving an example of what *would* be decent code. Most people would do `!DoSomething()` in stead of `DoSomething() == false` though.
Joren
Thanks mizipzor, I don't want to use such construction because it affects readability. Also I could be a bit unclear that I want to also include a catch statement. If you include try..catch block in your example it will further affects readability but I am interesed how you would resolve that issue?
Wodzu
Why do you want to include a catch and finally statement? Is it purely for readability? Many of the answers you have got focus on the debate that this should be used if, and only if, were working with error handling and not if its for readability or program flow. I strongly urge you to update your question and specify which of the three problems youre trying to tackle (error handling, readability, program flow)!
mizipzor
Three at once. As I stated in my updated question with C# example. Whats wrong with it? It's quite simple. I want to catch any unexpected errors and make sure that the code in the finally will always be executed, also I don't want to execute some methods in the finally block if the result of previous method(also in the finally block) is equal to false.
Wodzu
As I was corrected in another response, a 'finally' block will always be executed regardless if exceptions was thrown or not. Dont make the logic in finally depend to much on what happened in 'try'. Maybe your best bet here is using simple bool flags? Or some C# specific 'using' statements.
mizipzor
+2  A: 

In C#, finally is executed as well when return is called inside the try statement.

bool doSomething = false; bool doSomething2 = true;

        try
        {
            if( !doSomething )
            {
                Console.WriteLine ("not dosomething");
                return;
            }
            if( !doSomething2 )
            {
                Console.WriteLine ("not dosomething 2");
                return;
            }
        }
        finally
        {
            Console.WriteLine ("In finally");
        }
Frederik Gheysels
+3  A: 

Answer to updated question:

The reason you're having trouble doing this in an elegant way, is because you seem to be using a combination of return values and exceptions. You should consider manually raising an exception instead of using return values if the sitation is, well, exceptional.

Assuming there is a good reason for the return values however, I'm thinking it might be clearer to go without a finally block altogether, and to include a return at the end of the try block and also in your catch block. That would save you from passing the exception message in a messy way.

I can't really say what the best solution would be, since your code snippet does not show what Response would be if DoSomething() returns a non-zero value.


Original answer:

It depends a little on what you're trying to accomplish. Are exceptions actually being thrown in any of the methods? Otherwise there is no good reason to use a try-finally pattern. This would be equivalent (though maybe not advisable for readability):

bool doneEverything = DoSomething() && DoSomething2() && DoSomething3();
DoSomethingElse();

If there are exceptions being thrown, and handled at a higher level, I'd recommend isolating this code in a separate method, so you can use a return statement*.

void DoStuff()
{
    try
    {
        if (!DoSomething())
            return;

        if (!DoSomething2())
            return;

        if (!DoSomething3())
            return;
    }
    finally
    {
        DoSomethingElse();
    }
}

To answer your question about when the finally code block is executed: it is always executed, unless the executing thread terminates prematurely.

*: Some restructuring is recommended, because there is no equivalent of the Delphi Exit. The break statement comes closest, but it can only be used in loop constructs or switch blocks. To mimic Exit behavior, you would need goto and a label. We wouldn't want that, now would we? :)

Thorarin
THorarin it might work when void is returned, but what when I want to return something from a method? Please take a look at my updated question.
Wodzu
Thorarin I've tried goto but could manage to compile it. I don't mind goto, so if you could provide such example I would be grateful :)
Wodzu
What problem are you having trying to get it to compile? I have a feeling it's not directly related to the `goto` itself.
Thorarin
I got the message that SomeLabel is not in the scope of "goto SomeLabel" when I try to do: try{goto SomeLabel}finally{SomeLabel:}
Wodzu
+1 for pointing out the mix of return values and exceptions.
mizipzor
@Wodzu: You cannot jump directly into the finally block. Place the label **outside** it, just before the return statement. Even jumping with goto will not prevent the finally block from getting executed.
Thorarin
+2  A: 

What about switch case of course If you don't mean the finally in c# by saying finally block. default case is the finally block then and you can also find flow control example and here at msdn : http://tinyurl.com/yhr5ctt

static void Main(string[] args)
{
    switch (args[0])
    {
        case "copy":
            //...
            break;

        case "move":
            //...
            goto case "delete";

        case "del":
        case "remove":
        case "delete":
            //...
            break;

        default:
            //...
            break;
    }
}
Braveyard
+1 for an interesting solution but could you give an example how it would work with catching an exception?
Wodzu
@The problem is that it is not gonna catch an exception but it is similar with the code you wrote above, that's why I said that you could use it. But you can put this code under a try catch block. But in C#, in order to control the program flow, you use if-else and switch case conditions.
Braveyard
+1  A: 

In this sort of situation, understanding the question as dealing exclusively with the non-exception handling case, I would refactor the contents of the try into a private helper method, like this

void BranchOnContext()
{
        if (!DoSomething())
            return;

        if (!DoSomething2())
            return;

        // last one will drop out and return anyway
        DoSomething3();
}

void DoStuff()
{
    BranchOnContext();  // Assumed not to throw
    DoSomethingElse();  // Always the next thing to be executed
}

EDIT -- tracking the changed requirement

void DoStuff()
{
    string message = string.Empty;
    try {
        BranchOnContext();
    } catch (MyExpectedException me) { // only catch exceptions I'm prepared to handle
         message = me.Message;
    }  
    DoSomethingElse(message);  // Always the next thing to be executed
}
Steve Gilham
Thanks Steve. I think this is very close to what I want to obtain. Could you extend your example to include an exception handler like in the code that I provided in my updated question?
Wodzu
Extended as requested, noting that I only want to handle some exception type (alternatively if there is no sensible common base catch any Exception, and if it isn't of the types you want, then throw; otherwise as just extract the message.
Steve Gilham
Thanks Steve. I find it nice and clean +1. With little modification (message also dependend on DoSomething result) I can achieve expected behavior. What do you think about my solution?
Wodzu
A: 

Taking another crack at this with the updated info:

I want DoSomethingElse to be executed always and I want it to include message from possible exception

If any of the DoSomething's return 0, null is returned. If not, the generic message is created. If there was an exception, it is caught and a message with its info is returned. How about this?

XElement OrderStatus(q_order_status Request)
{
  try
  { 
 if (DoSomething() != 0 )
 {
   return null;
 }
 else
 {
   return new XElement("SomeTag", "SomeResponse");
 }
  }
  catch(Exception e)
  {
 // catch some errors and eventually pass the e.Message to the Response
 return new XElement(e.tag, e.response);
  }
}

Im still struggling with how to, in a good way, put finally into this.

mizipzor
Thanks mizipzor for putting your time onto this. The problem is that: Response has to be returned in every case. If one of the DoSomethings"s is equal to 0 the reason must be given in Response.If all DoSomething's are passed then Response must contain information that they are passed. But it will be sufficent to replace null in your example with "return new XElement("SomeTag", "SomeResponse"). However as you pointed out there is no finally block...
Wodzu
If the function would return 0, instead then throw an exception. With this setup it will be caught and its relevant information passed on.
mizipzor
A: 

This appears to replicate the delphi:-

try
{
  if(DoSomething())
    if(DoSomething2())
      DoSomething3();
}
finally
{
  DoSomethingElse();
}

an alternate style (some people will hate this style, others will love it.):-

try
{
  DoSomething() && DoSomething2() && DoSomething3();
}
finally
{
  DoSomethingElse();
}

I get the impression you want some other behaviour though?

Goto version?

try
{
  if (!DoSomething())
    goto Exit;

  if (!DoSomething2())
    goto Exit;

  if (!DoSomething3())
    goto Exit;

Exit:;
}
finally
{
  DoSomethingElse();
}

Note the irritating ; after the label, it seems a label must precede a statement.

Just had an epiphany:-

Func<bool>[] somethings = new Func<bool>[] {DoSomething, DoSomething2, DoSomething3};
try
{
  foreach (Func<bool> something in somethings)
  {
    if (!something())
      break;
  }
}
finally
{
  DoSomethingElse();
}
JonB
Thanks JonB for the example. Yes, I wanted to avoid nested if's because IMHO it makes code harder to read. All my question is about controlling the program flow to increase readability. I admin that on your example it looks very clear but when you would have to setup Response after each of the DoSomethings it will get messy.
Wodzu
Added a couple of other possibles, I think the loop might be the tidiest.
JonB
A: 

Guys this is my proposal. I find it quite similar in behavior to the Delphi's one which I have shown on the beginning. I am interested in your comments. Response is dependent on the DoSomethings result.

XElement OrderStatus(q_order_status Request)
{
  XElement Response;
  int result = 0;
  string Message = "";
  try
  { 
    result = DoSomething1();
    if (result != 0)
    {
      throw new DoSomethingException("DoSomething1 has failed!");
    }
    result = DoSomething2();
    if (result != 0)
    {
      throw new DoSomethingException("DoSomething2 has failed!");
    }
    result = DoSomething3();
    if (result != 0)
    {
      throw new DoSomethingException("DoSomething3 has failed!");
    }
    Message = "All tests has been passed.";
  }
  catch(DoSomethingException e)
  {
    Message = e.Message;
  }
  catch(Exception e)
  {
    Message = e.Message;
  }
  finally
  {
    Response =  new XElement("SomeTag", Message);
  }
  return Response;
}

What do you think?

Wodzu
A: 
void funcA()
{
    if (!DoSomething())
        return;

    if (!DoSomething2())
        return;

    if (!DoSomething3())
        return;
}

void funcB()
{
    funcA();
    DoSomethingElse;
}
Brian