views:

872

answers:

13

I have the following C# code. Whenever an exception is caught, say at line 1, I am never able to reach other lines (2, 3, 4, etc).

try
{
    line1
    line2
    ...
}
catch (Exception ex)
{
    ...
}

Is it possible, in C#, to say that if line 1 generates an exception, just continue on to the other lines (2, 3, 4, etc)?

+2  A: 

you can wrap just line 1 in a try catch block.

Scott M.
+5  A: 

just put a try catch around line1

try
{
    try
    {
        line1
    }
    catch (Exception ex)
    {
       ...
    }

    line2
    ...
}
catch (Exception ex)
{
    ...
}

Frederik is right though you really need to be careful when doing this. It should be used on a case by case basis. Only when you know that the process should continue should you use it. Otherwise you should handle the exception accordingly.

jmein
not really good practice...imo
Stan R.
this will create more headaches than it will solve in the long run.
jlech
I agree it is not always the best solution but there are times when you need to continue. Such as when you are creating an order and there is an error in the order creation process. It would be a good idea to do add a try catch around blocks that have a possibility of breaking. That way you can still get all of the information for the order and your client will not have to completely recreate the order.
jmein
What if it fails in line 2 next - jsut keep eatng exceptios until the code finishes working?
Davy
poster says it fails "say at line 1" - A well thought out exception handling plan would be better advice in my opinion.
Davy
@Davy I agree with you. I am just saying that at times you need to continue processing. Ordering is the best example I can think of. The more information you know about their order, the easier it is to discover how the error occurred and work out a solution. And maybe even fix their order so that they dont have to recreate it again.
jmein
@Davy If that is the situation the first thing he needs to do is look at his code and rethink what he is doing. I was just saying that it is an option and it should be used sparingly.
jmein
+16  A: 

Exceptions should not be ignored. :)
They exists and are thrown for a reason: an exceptional situation has occured, a certain condition is not met, and I cannot continue working ...

It is possible to ignore exceptions, if you put a try / catch block around each line of code, but I don't think that you really want to do that ...

Frederik Gheysels
In cases lets say where you are creating an order and there is an error in the order creation process. It would be a good idea to do add a try catch around blocks that have a possibility of breaking. That way you can still get all of the information for the order and your client will not have to completely recreate the order.
jmein
I think this is a good primer on why/when to catch exceptions: http://mikehadlow.blogspot.com/2009/08/first-rule-of-exception-handling-do-not.html
Greg
And just because it is in a try catch block does not mean you are ignoring the problem. You can log the problem so that it can be looked at and fixed, but the process can continue. Yes there will be times that everything should stop at the first step if it fails, but that is not always the case.
jmein
Offcourse you can log the problem and take appropriate action.But, handling an exception does not mean by default that the process can continue. You're not sure that you can get the information that you need to. You're not sure whether you can execute the operation you have to, etc...
Frederik Gheysels
I know what you mean. All I am saying is that is really a case by case basis. You should not have the try catch block unless you have really thought out why it is there and you know that the process should continue.
jmein
@jmein: Do you think your customers will be happy when they only get half their order. Or perhaps they will, if the thing that happened to break was the subtotal computation.
erikkallen
@erikkalen Oh yeah that is exactly what I am saying. You should give your client half of their order. They wont notice will they. Well anyways I guess I need to explain. If you create your order process properly you can still have all the data even if part of the process failed. You can store all of the data into a file for saving state purposes so that even when the order process fails you can correct the order manually without the client having to worry about it. You are notified of the error so that you know there was something wrong with the order.
jmein
erikkalen You also need to pay attention a little more. I said it should be used in a case by case basis. If it something very important and you obviously cant continue then you dont. You can handle the error accordingly
jmein
+1  A: 

You can always do

try 
{
   line1
}
catch (Exception ex)
{
}
line2
...

But there is nothing like a 'retry' keyword.

Brian
If you intend not to use the exception I would advise you remove the ex from the catch.
James
+1  A: 

As suggested, you should wrap the try catch around line1 in this particular example. However, for future note you should only really ever have conditions in your try catch block that you only want to be completed IF there are no exceptions.

James
+4  A: 

If there's code that you always want to be executed, even if an exception is thrown, even if the exception either doesn't get caught in the catch block, or the catch block re-throws or throws a new exception, it should go in the "finally" block:

try
{
  do(something);
}
catch (InvalidArgumentException ex)
{
  onlyDealWithOneExceptionType();
}
finally
{
  always.runs(no, matter, what);
}
Cylon Cat
It's worth mentioning that always.runs() might throw an exception itself, so the 'finally' code should generally be 'safe'.
axel_c
A: 
try
{
    line1
    line2
    ...
}
catch (Exception ex)
{
    ...
}
finally
{
    if(line1ErrorOccured)
    {
        line2
        ...
    }
}

not given it too much thought though

Daniel Pokrývka
+3  A: 

You can isolate each line into a try-catch block, however that just wreaks of codesmell to me. If you are certain that the lines after line one do not throw exceptions, or need to be executed regardless of the exception and will not throw additional errors, you can add a finally block after the first catch. Example:

try{
  line 1;
}
catch(Exception exc){
  //Error handling logic here
}
finally{
  line 2;
  line 3;
  .
  .
  .
  line n;
}
jlech
This will do the same thing as mine except for the code in the finally block could throw an exception and you would not handle it. It is not safe to assume that it would not throw an exception.
jmein
And I definitely was not recommending putting each line in a try catch block. It should only be used when you know there is a possibility of a specific line breaking and you know the process should continue if it does.
jmein
I agree that it's not safe to assume that code in a finally block won't break, which is why a stressed it as a prerequisite for the finally block. It differs from your solution in the sense that it scales nicely and is easier to maintain/read instead of having to nest try block in try block in try block etc. Also, in your example, if the an inner exception type is not caught, it will cascade up to parent catch blocks and possibly skip over a whole scope of code.
jlech
The catch would get the exception so it should not be an issue. Anyways, your solution would be a good use when you are disposing of objects that may have been used in try catch. That way they will be disposed even if an exception is thrown.
jmein
+1  A: 

You can put the other lines in a finally clause, but that would be quite ugly, especially if these can throw exceptions as well...

You should recover from the first exception, and then carry on to the next line, wrapping each in a try/catch statement.

Philippe
Finally blocks aren't ugly; they are there for cleanup. Suppose you have an exception during a database operation in the Try block. The finally block is where you should close the connection and dispose of the connection object.
Cylon Cat
That's why I said it was ugly. My point was that assuming line2 and following are doing the same kind of work as line1, they shouldn't be in a finally clause, or it'd be ugly.
Philippe
+7  A: 

You could create a SkipOnError method like this:

private SkipOnError(Action action)
{
    try 
    {
        action();
    }
    catch
    {
    }
}

Then you could call it like so:

try
{ 
    SkipOnError(() => /*line1*/);
    line2;
    line3;
} catch {}

Edit: This should make it easier to skip a given exception:

private SkipOnError(Action action, Type exceptionToSkip)
{
    try 
    {
        action();
    }
    catch (Exception e)
    {
        if (e.GetType() != exceptionToSkip) throw;            
    }
}

NOTE: I'm not actually suggesting you do this - at least not on a regular basis, as I find it rather hacky myself. But it does sort of show off some of the functional things we can now do in C#, yay!

What I would really do is this: Refactor line1 into a method (Extract Method). That new method should handle any foreseeable exceptions (if they can be handled) and thus leave the caller in a known state. Because sometimes you really want to do line1, except, maybe it's ok if an error happens...

Daren Thomas
This is dastardly...
Jason Punyon
The idea is not bad, but at least catch a specific error... skipping any error is very dangerous and should not be done.
Meta-Knight
What about nesting SkipOnError?
leppie
.. or provide an Action<Exception> as your exception handler. Still, looks rather dirty to me, though :)
cwap
This is essentially the same as my answer, except you had time to post the code too ;-)
Phil Nash
+1  A: 

As others have said, ensure first that "ignoring" the exception is what you really want to do. If it still is, and the syntactic overhead of all the try-catch's is too high, you could wrap it up with the execute-around idom.

I don't have time to sketch out all the code right now - but what you'd do is write a method that takes an anonymous delegate and executes it within a try-catch (maybe logging any exceptions, or filtering ones that are "ok"). Call this method something like tryDo. You could then write you code something like this:

tryDo( delegate(){ line1; } );
tryDo( delegate(){ line2; } );

It's still a little verbose, but then you don't want to make this stuff too easy. It's just enough overhead to make you keep wondering if it's the right thing to do :-)

Phil Nash
A: 

If it's possible to handle your exception and continue, you should localize your try/catch blocks.

try
{
  line1;
}
catch (ExpectedException e)
{
  // Handle your exception, prepare data for the next lines
  // Could you have prevented the exception in the first place?
}

try
{
  line2;
  line3;
}
catch (AnotherExpectedException e)
{
  // Maybe this exception you can't continue from. Perhaps log it and throw;
}

Remember that exceptions are exceptional. If an exception is thrown, something should have gone wrong. You should try to prevent the exceptions in the first place.

Will Eddins
A: 

You will need reifiable continuations to do that. The CLR and C# does not support that, and will probably never do so. :(

leppie