I couldn't find any Microsoft official resource that shows how code below the finally block execute, the only information in regards to it is the book CLR via C#, the author says:
Code below the finally block executes if no exception is thrown within the try block or if a catch block catches the exception and doesn't throw or re-throw an exception.
Let's say we have the following code:
class Program {
static void Main(string[] args) {
SomeMethod1();
Console.ReadLine();
}
static void SomeMethod1() {
try {
SomeMethod2();
}
finally {
Console.WriteLine("SomeMethod1 finally");
}
Console.WriteLine("SomeMethod1 last");
}
static void SomeMethod2() {
try {
SomeMethod3();
}
catch (DivideByZeroException e) {
Console.WriteLine("SomeMethod2 caught");
}
finally {
Console.WriteLine("SomeMethod2 finally");
}
Console.WriteLine("SomeMethod2 last");
}
static void SomeMethod3() {
try {
SomeMethod4();
}
finally {
Console.WriteLine("SomeMethod3 finally");
}
Console.WriteLine("SomeMethod3 last");
}
static void SomeMethod4() {
try {
Int32 i = 0;
var c = 3 / i;
}
finally {
Console.WriteLine("SomeMethod4 finally");
}
Console.WriteLine("SomeMethod4 last");
}
}
and the output is:
SomeMethod4 finally
SomeMethod3 finally
SomeMethod2 caught
SomeMethod2 finally
SomeMethod2 last
SomeMethod1 finally
SomeMethod1 last
You can see that "SomeMethod4 last" and "SomeMethod3 last" doesn't get printed.
"SomeMethod4 last" doesn't get printed is easy to understand as SomeMethod4 throw an exception and there is no catch block to catch the exception, so it doesn't meet the requirement that specified by the author, fair enough.
But why "SomeMethod3 last" doesn't get printed? there is no exception thrown at SomeMethod3, just like SomeMethod1, so why "SomeMethod1 last" get printed while "SomeMethod3 last" doesn't? Is any Microsoft official resource that explain the mechanics of it?
When the exception is thrown in SomeMethod4, it is flowing up to the calling method which is SomeMethod3. Think of it as if SomeMethod4 was actually inline inside SomeMethod3 like this.
static void SomeMethod3()
{
try
{
try
{
Int32 i = 0;
var c = 3 / i;
}
finally
{
Console.WriteLine("SomeMethod4 finally");
}
Console.WriteLine("SomeMethod4 last");
}
finally
{
Console.WriteLine("SomeMethod3 finally");
}
Console.WriteLine("SomeMethod3 last");
}
The reason SomeMethod2 Last is being run is because it is the part that actually catches the exception.
If you add a catch to SomeMethod3, you will see that SomeMethod3 Last gets printed as well.
Exceptions break the flow of the application, and basically don't stop going back up the call stack until it reaches a catch statement. Technically the exception is being thrown inside SomeMethod1, but its being caught in SomeMethod2 which means the exception never reaches SomeMethod1.
Related
My simple example is:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex)
{
var messageWithStackTrace = ex.ToString(); //line 28.
Console.WriteLine(messageWithStackTrace);
}
}
The console output is:
System.Exception: Exception 2
at Program.FixedUnalterableMethod() in ...\Program.cs:line 16
at Program.Main(String[] args) in ...\Program.cs:line 24
The question is, how to be informed that the Exception 1 has occured?
Is there a way how to include Exception 1 in my StackTrace (in line 28.) ?
Of coure I can't modify the FixedUnalterableMethod() method!
Yes, this is possible, though pretty nasty!
It is a little known fact that CLR exceptions do not cause the execution of finally blocks until the exception has actually been caught. This is disguised somewhat because if an exception is not caught (and makes it out of Main) then the default behaviour of the CLR hosting code is to run finally blocks for you, giving the illusion that they always run.
However, there is a way to examine an exception before catching it, to decide if you want to catch it. Try this:
static bool StoreFirstException(Exception x, Action<Exception> store)
{
if (x.Message == "Exception 1")
{
store(x);
}
return true;
}
static void Method1()
{
Exception firstException = null;
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex, x => firstException = x))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
The catch... when feature lets you write a boolean expression to examine the exception. Here I check the message (the only distinguishing fact you've given me) and if it's the first exception I pass it to the store action.
The caller uses this callback to stash the first exception.
Then it votes to catch, which only then causes the finally block to execute, which throws the second exception. The same when clause examines it but this time doesn't offer it to store. So then I have both exceptions in the catch block and I log them both. My console shows the two exceptions with the correct source line numbers.
Here's version that doesn't look at the message; it just assumes the first exception it see must be the interesting one. Also it's neater to use a nested function:
static void Method1()
{
Exception firstException = null;
bool StoreFirstException(Exception x)
{
if (firstException == null) firstException = x;
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
If the "exception type" is literally the same you probably have little choice but the examine the Message property, which can be problematic to say the least.
Looking at that code again you will only ever see the 1 exception anyway, the one on line 16.
Thanks to #Daniel Earwicker the working solution is:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
bool CatchException(Exception ex)
{
//Log...
Console.WriteLine(ex.ToString());
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (CatchException(ex))
{
//do something with the lastest exception
}
}
I am quite confused with how exceptions are getting thrown in C#. If an exception occurs, in the try block,
1.it gets thrown to the catch block,
2. If and only if the catch block catches it the finally block will be executed.
3. The finally block gets executed last, provided the catch statement caught it.
However, when I try to run the program below, the output is A,B not BA.Is there something wrong with my understanding? Thank you.
class Program
{
public static void Main(string[] args)
{
try
{
int a = 2;
int b = 10 / a;
try
{
if (a == 1)
a = a / a - a;
if (a == 2)
{
int[] c = { 1 };
c[8] = 9;
}
}
finally
{
Console.WriteLine("A");
}
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("B");
}
Console.ReadLine();
}
}
The exception occurs in a==2, and I know the outer catch will catch this exception. However, the finally is being executed first? Any reason as to why this is showing?
edited
From C# docs we know Finally block gets executed whether or not an exception has occured.
However, my finally block never gets executed and in return I am getting a run time error
class Program
{
public static void Main(string[] args)
{
try
{
int a = 2;
int b = 10 / a;
try
{
if (a == 1)
a = a / a - a;
if (a == 2)
{
int[] c = { 1 };
c[8] = 9;
}
}
finally
{
Console.WriteLine("A");
}
}
finally{
Console.WriteLine("finally");
}
Console.ReadLine();
}
}
finally executes when control leaves the try block to which it is attached for any reason; not just if there was a catch block at the same level - that would be a fault handler (in CLR terms) which I think we still cannot do in C#.
So it enters the finally that prints A because control is leaving that try block. It's leaving it because of an exception that's being caught in an outer catch block. That doesn't change any timings/orderings however.
Note that there are some oddities that are possible if the exception is entirely uncaught anywhere in your code. Exception handling happens in two phases. In the first phase, it's trying to locate an appropriate catch clause for the exception, and that can include executing guard clauses (when, C#6 and later). During the second phase, it unwinds the stack and executes any finally clauses as the nesting requires, before reaching the correct level at which the catch clause that will handle the exception is defined1.
I believe that in some environments, if the first phase fails to locate an appropriate exception handler (catch clause) at all, the entire managed environment may be torn down. In such circumstances, the finally clauses aren't executed.
All that is required by a standards conforming CLR is described in the MS Partition I.pdf document, found on ECMA C# and Common Language Infrastructure Standards. Section 12.4.2.5 states:
When an exception occurs, the CLI
searches the array for the first protected block that
Protects a region including the current instruction pointer and
Is a catch handler block and
Whose filter wishes to handle the exception
If a match is not found in the current method, the calling method is searched, and so on. If no match is found
the CLI will dump a stack trace and abort the program.
(My emphasis)
1Illustrated using a variant of Flydog57's example, also C# 7 local functions:
using System;
namespace PlayAreaCSCon
{
internal class Program
{
static void Main(string[] args)
{
TestTryCatchFinally();
Console.WriteLine("Complete");
Console.ReadLine();
}
private static void TestTryCatchFinally()
{
try
{
Console.WriteLine("Start Outer Try");
try
{
Console.WriteLine("Start Inner Try");
throw new Exception("Exception from inner try");
}
finally
{
Console.WriteLine("In Inner Finally");
}
}
catch (Exception ex) when (GuardHelper(ex))
{
Console.WriteLine("In outer catch");
}
finally
{
Console.WriteLine("In outer finally");
}
bool GuardHelper(Exception ex)
{
Console.WriteLine("In outer guard");
return true;
}
}
}
}
This prints:
Start Outer Try
Start Inner Try
In outer guard
In Inner Finally
In outer catch
In outer finally
Complete
Illustrating the two-pass nature of the exception handling (that In outer guard is printed before In Inner Finally)
In your first code, the reason that the finally (A) runs before the catch (B) is because when the exception is thrown, you exit the inner block (causing the finally to run) before the outer block's catch comes into play. Consider this code:
private void TestTryCatchFinally()
{
try
{
Debug.WriteLine("Start Outer Try");
try
{
Debug.WriteLine("Start Inner Try");
throw new Exception("Exception from inner try");
Debug.WriteLine("End of Inner Try - never reaced");
}
//remove this catch block for second test
catch (Exception)
{
Debug.WriteLine("In inner catch");
}
//end of code to remove
finally
{
Debug.WriteLine("In Inner Finally");
}
}
catch (Exception)
{
Debug.WriteLine("In outer catch");
}
finally
{
Debug.WriteLine("In outer finally");
}
}
If I run this code, I get this output:
Start Outer Try
Start Inner Try
Exception thrown: 'System.Exception' in MyTestApp.exe
In inner catch
In Inner Finally
In outer finally
Which is what you expect. But, if I remove the inner catch block (as noted in the code), I get this output:
Start Outer Try
Start Inner Try
Exception thrown: 'System.Exception' in MyTestApp.exe
In Inner Finally
In outer catch
In outer finally
In this case, as soon as execution exits the inner try block, the finally code executes. Then the outer catch block has it's turn.
If you have a single try-catch-finally block, it's true that catch precedes finally. But here, the try-finally and try-catch blocks are being run in order of innermost to outermost. Therefore the finally runs first.
It should look something like this (depents on what you are actually trying to do)
class Program
{
public static void Main(string[] args)
{
try
{
int a = 2;
int b = 10 / a;
if (a == 1)
a = a / a - a;
if (a == 2)
{
int[] c = { 1 };
c[8] = 9;
}
}
catch (IndexOutOfRangeException e)
{
//Do something when something in try block throws error
Console.WriteLine("B");
}
finally
{
//This code will ALWAYS execute
//Even when there is no error, A will be written to console
Console.WriteLine("A");
}
Console.ReadLine();
}
}
I may be missing something. Don't you want the following?
try
{
}
catch (Exception ex)
{
}
finally
{
}
By using a finally{} block, you can ensure that some statements will always run
This issue drives me insane, as I can't see what's causing it. The behavior is unexpected and I just can't see how it can occur. When I execute my plugin using the code below, I get the error message "bada boom". Just as expected.
public void Execute(IPluginExecutionContext context)
{
throw new Exception("bada boom");
try
{
throw new Exception("bada bing");
...
} catch (Exception) { }
...
}
However, when I comment out the first throw, I don't get to see "bada bing". Instead, I get "object not set to a reference"! What the duck?! (Typo intended.)
public void Execute(IPluginExecutionContext context)
{
//throw new Exception("bada boom");
try
{
throw new Exception("bada bing");
...
} catch (Exception) { }
...
}
Here's graphics for the issue.
In your first example the exception is handled at the caller level and up till a catch block is found. In the second example the exception is handled in the mandatory catch or finally block associated with the try of the Execute method.
So in the code inside that catch or finally block you have a null reference exception
void Main()
{
try
{
Execute();
}
catch(Exception x)
{
Console.WriteLine("In main: " + x.Message);
}
}
public void Execute()
{
// Goes to the catch block in main
//throw new Exception("bada boom");
try
{
// Goes to the catch block associated with this try
throw new Exception("bada bing");
}
catch(Exception x)
{
// Uncomment this to see the null reference exception in main
// Console.WriteLine("In Execute: " + x.InnerException.Message);
Console.WriteLine("In Execute:" + x.Message);
}
}
Well, of course, when I say mandatory I want to say that you cant write
try
{
....
}
without a catch or a finally clause following the try. And you can write a catch or finally block without code, but you can't omit one of the two keywords and its block
How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}
I'm trying to write some code that catches a particular exception and throw a more useful one for something higher up the call stack to deal with but also catch more general exceptions and handle them.
The code is something like this:
try
{
// Do stuff
}
catch (SomeException e)
{
throw new SomeExceptionWithContextInfo();
}
catch (Exception e)
{
// Handle unexpected exception gracefully
}
The problem I'm having is that the general exception is catching my new exception. is there a way to avoid this?
My current solution involves checking the type of the exception and throwing it again if it's type is what I just created.
The code you've posted should work, as shown in this test app:
using System;
class OtherException : Exception {}
class Test
{
static void Main(string[] args)
{
try
{
Foo();
}
catch (OtherException)
{
Console.WriteLine("Caught OtherException");
}
}
static void Foo()
{
try
{
string x = null;
int y = x.Length;
}
catch (NullReferenceException)
{
throw new OtherException();
}
catch (Exception)
{
Console.WriteLine("Caught plain Exception");
}
}
}
This just prints "Caught OtherException" not "Caught plain Exception". Are you sure you don't have a nested try block in your real code? Could you post a short but complete example which shows your problem?
Do you really need to catch Exception in your method though? That's very rarely a good idea.
You're doing it right. The general exception will not catch the specific one.
The code you posted is the way to do it (catch for more specific exception must appear first).
I suggest looking again at the code, as either they are not in that order, or the code isn't actually throwing that exception type.
Here is a link on msdn about try-catch: http://msdn.microsoft.com/en-us/library/0yd65esw(VS.80).aspx
Don't catch general exceptions might be the answer? Find out which Exceptions that can be thrown and catch them separately.
try { // Outer try/catch
DoSomething();
try {
/* */
} catch(NotGeneralException e) {
/* */
} catch(AnotherNotGeneralException e) {
throw new SomeOtherException("Exception message");
}
} catch(SomeOtherException e) {
/* */
}
Alternatively only catch a general exception and rethrow SomeOtherExcepion
try {
} catch(Exception e) {
throw new SomeOtherException("Exception message");
}