Do I have to break after throwing exception?
Asked Answered
P

6

23

I'm writing a custom class in C# and I'm throwing a couple exceptions if people give the wrong inputs in some of the methods. If the exception is thrown, will any of the code in the method after the throw still be executed? Do I have to put a break after the throw, or does a throw always quit the method?

Physicalism answered 13/6, 2009 at 6:20 Comment(8)
Split this up into three questions. (1) Will any of the code in the method after the throw be executed? YES. If the exception was inside a try then code inside matching catch blocks or finally block will be executed. If there is no try block then NO. Control branches to the nearest enclosing finally, catch or (in vb) exception filter block up the stack.Tailwind
(2) Do I have to put a break after the throw? NO, never do that. The end point of the throw statement is not reachable; a throw is treated as a goto by the compiler. A statement immediately following a throw is not reachable and will never execute.Tailwind
(3) Does a throw always quit the method? NO. If the throw is in a try and the try has a matching catch block then the catch block can "eat" the exception. Only if there is no catch block does the exception do a non-local goto up the call stack.Tailwind
If you have more questions about this, I recommend reading the C# specification; all this behaviour is clearly documented.Tailwind
Finally, it sounds like you are throwing "boneheaded" exceptions, as in "hey boneheaded caller, I told you to never give me that data". That's great because it prevents bugs in callers. But if you do that, you should make sure that the caller has some way of knowing what you expect! If the caller cannot figure out whether you're going to throw or not based on your documentation, then you haven't made a boneheaded exception, you've made a vexing exception. See blogs.msdn.com/ericlippert/archive/2008/09/10/… for details.Tailwind
Thank you eric. I read some stuff on exceptions before asking, but your comments made it very clear to me. Much appreciated.Physicalism
@Eric, for languages that have assert, would you say that an assert is a good way for rejecting bonehead errors? Like, say, in C++ one can throw (but any exception can be caught by catch(...)!), and we can assert. Would you say assert is a better way for boneheaded errors than throw in this case?Wilhelminawilhelmine
@Johannes: Good question. My position: (1) an assertion should be always true no matter what. That is, your user is using your software and there is no input they can give you that causes the assertion to fire. (2) there should be some user input which triggers every exception. An exception which cannot be thrown is dead code, is untestable, and should be eliminated. So there you go: if the unexpected error is possible then throw an exception. If it is impossible then document that fact with an assertion, so that you'll be told if your supposition of impossibility was incorrect.Tailwind
W
37

When you throw an exception, the next code to get executed is any catch block that covers that throw within the method (if any) then, the finally block (if any). You can have a try, a try-catch, a try-catch-finally or a try-finally. Then, if the exception is not handled, re-thrown by a catch block or not caught at all, control is returned to the caller. For example, you will get "Yes1, Yes2, Yes3" from this code ...

try
{
    Console.WriteLine("Yes1");
    throw (new Exception());
    Console.WriteLine("No1");

}
catch
{
    Console.WriteLine("Yes2");
    throw;
    Console.WriteLine("No2");
}
finally
{
    Console.WriteLine("Yes3");
}

Console.WriteLine("No3");
Wellstacked answered 13/6, 2009 at 6:27 Comment(2)
This would be an exception (little e) to my answer. I was thinking along the lines of an Exception that would be used in the common context and not be used like a GOTO statement.Froebel
@jarrett: This is exactly the common context, except that the throw is hidden inside function calls.Sheatfish
F
26

Throw will move up the stack, thus exiting the method.

Froebel answered 13/6, 2009 at 6:22 Comment(1)
Thank you. Sorry to ask such a basic question.Physicalism
M
4

I recommend stepping through your program with a debugger then you'll see for yourself what is going on. Very useful for learning!

Mecham answered 13/6, 2009 at 14:12 Comment(2)
This is a "tip" and not an answer to the original question.Elongate
Wow my "not an answer" flag was disputed.Montane
E
2

I came here looking for an answer to the original post and almost missed a very valuable answer posted by Eric Lippert. Here's his answer posted in the comments:

Split this up into three questions.

(1) Will any of the code in the method after the throw be executed?
YES. If the exception was inside a try then code inside matching catch blocks or finally block will be executed. If there is no try block then NO. Control branches to the nearest enclosing finally, catch or (in vb) exception filter block up the stack.

(2) Do I have to put a break after the throw?
NO, never do that. The end point of the throw statement is not reachable; a throw is treated as a goto by the compiler. A statement immediately following a throw is not reachable and will never execute.

(3) Does a throw always quit the method?
NO. If the throw is in a try and the try has a matching catch block then the catch block can "eat" the exception. Only if there is no catch block does the exception do a non-local goto up the call stack.

If you have more questions about this, I recommend reading the C# specification; all this behavior is clearly documented.

Finally, it sounds like you are throwing "boneheaded" exceptions, as in "hey boneheaded caller, I told you to never give me that data". That's great because it prevents bugs in callers. But if you do that, you should make sure that the caller has some way of knowing what you expect! If the caller cannot figure out whether you're going to throw or not based on your documentation, then you haven't made a boneheaded exception, you've made a vexing exception. See http://blogs.msdn.com/ericlippert/archive/2008/09/10/vexing-exceptions.aspx for details.

Elongate answered 23/3, 2017 at 18:6 Comment(1)
Regarding your first point: C# now has exception filters too; it's not just for VB anymore.Tailwind
S
1

If you've wrapped your code in a Try...Catch...Finally block, then the code under Finally will always execute. For example:

Try
  ' do some stuff here
  ' Examine user input
  If user input isn't valid
      Throw new exception
Catch
   Throw ' Just re-throws the same exception
Finally
   ' This code will execute, no matter what - exception or not
End Try
Stalingrad answered 13/6, 2009 at 6:29 Comment(0)
M
1

As an aside to your actual question: you might want to rethink using exceptions to provide validation info back to the user.

Raising exceptions is expensive resource-wise and slow. If you have a number of validation rules that you need to apply then write specific code for these - you should probably only rely on exception handling for things you don't anticipate.

Moramorabito answered 13/6, 2009 at 11:7 Comment(2)
I was wondering about this too. I'm writing a high score class, and the constructor can take a "max" param. which indicates the max score available. well if they pass a number larger than my class supports, I was throwing an exception because I didn't want the constructor to finish with bad info. I'm new at this, is there a better way to do it?Physicalism
This is a comment and not actually an answer to the OP.Elongate

© 2022 - 2024 — McMap. All rights reserved.