in C# try-finally how to catch the original exception - c#

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
}
}

Related

How to resume second method after first method throws an exception C#

While looking on C# try catch tutorial, I got following question. My sample code as follows,
Inside mainMethod() , I need to call three separate methods. Inside testMethodOne(), I need to handle exception as. If testMethodOne() throws exception, without executing testMethodTwo(dt), mainMethod() throwing exception. I need to call testMethodTwo(dt); and testMethodThreee(dt); if testMethodOne() throws exception, how can I do it.
public void MainMethod(data dt){
try{
testMethodOne(dt);
testMethodTwo(dt);
testMethodThreee(dt);
}catch(Exception ex){
throw ex;
}
}
public void testMethodOne(dt){
try
{
// Block of code to try
}
catch (Exception e)
{
// Block of code to handle errors
}
}
I understood your question as follows (but I might be wrong, your questions is not very clear):
Even if one of your testMethods throws an exception, you still want to continue in the normal program flow with the other methods. If at least one of the method failed, mainMethod could then report this as AggregateException.
public void MainMethod(data dt)
{
var exceptions = new List<Exception>();
try
{
testMethodOne(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodTwo(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodThreee(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
It seems as if you want exceptions to alter the flow of your main method without breaking everything. One easy method is to make each 'testmethod' return a boolean.
public bool testMethodOne(dt){
try
{
// Block of code to try
return true;
}
catch (Exception e)
{
// Block of code to handle errors
return false;
}
}
Then in your main code you can go
if(!testMethodOne(dt))
if(!testMethodTwo(dt))
if(!testMethodThree(dt))
//log that all methods failed
The above snippet would try each method until it finds one that succeeds. If that's not the behaviour you are looking for can you reword your question to make it clearer? If you want the opposite to happen just get rid of the ! and it will go until one fails. Alternatively you could put a throw in your catch statement in each of the testMethods, and that would stop execution once one is reached as well.

When Rethrow a Exception in c#?

I have read about why we need to throw an exception and Rethrow it. But I have confused about when Rethrow an exception? I added an example when I put throw in CalculationOperationNotSupportedException catch, and after that, I compared Stack Trace with Rethrowing and without Rethrowing. It's the same 99%, but when you rethrow an exception, it just adds location.
Of course, if you accurately two stack trace. Line 35 is "throw" location number, and line 28 is int result = calculator.Calculate(number1, number2, operation);
I think Stack Trace without rethrowing in here is better. What do you think about that?
Stack Trace without rethrowing(throw) I commented it.
at ConsoleCalculator.Calculator.Calculate(Int32 number1, Int32
number2, String operation) in
C:\Users\Behnam\Desktop\c-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Calculator.cs:line
25 at ConsoleCalculator.Program.Main(String[] args) in
C:\Users\Behnam\Desktop\c-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Program.cs:line
28
Stack Trace with rethrow in catch (CalculationOperationNotSupportedException ex)
at ConsoleCalculator.Calculator.Calculate(Int32 number1, Int32 number2, String operation) in C:\Users\Behnam\Desktop\c-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Calculator.cs:line 25
at ConsoleCalculator.Program.Main(String[] args) in C:\Users\Behnam\Desktop\c-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Program.cs:line 35
public int Calculate(int number1, int number2, string operation)
{
string nonNullOperation =
operation ?? throw new ArgumentNullException(nameof(operation));
if (nonNullOperation == "/")
{
try
{
return Divide(number1, number2);
}
catch (ArithmeticException ex)
{
throw new CalculationException("An error occurred during division", ex);
}
}
else
{
throw new CalculationOperationNotSupportedException(operation);
}
}
static void Main(string[] args)
{
var calculator = new Calculator();
int number1=1;
int number2=1;
string operation = "+";
try
{
int result = calculator.Calculate(number1, number2, operation);
DisplayResult(result);
}
catch (CalculationOperationNotSupportedException ex)
{
// Log.Error(ex);
WriteLine(ex);
throw;
}
}
There are two articles on the thematic I link often. I consider them required reading.
https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/
https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET
At the basic, you should not catch an exception if you can not handle it. But sometimes, you have to make exceptions (no pun intended) to any rule about Exception. You might have to catch wider and then apply "catch and release" to the extra Exceptions you got. For example, here is my atempt at repilicating TryParse:
//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).
bool TryParse(string input, out int output){
try{
output = int.Parse(input);
}
catch (Exception ex){
if(ex is ArgumentNullException ||
ex is FormatException ||
ex is OverflowException){
//these are the exceptions I am looking for. I will do my thing.
output = 0;
return false;
}
else{
//Not the exceptions I expect. Best to just let them go on their way.
throw;
}
}
//I am pretty sure the Exception replaces the return value in exception case.
//So this one will only be returned without any Exceptions, expected or unexpected
return true;
}
No, your understanding of how throwing and rethrowing works is incorrect.
When you throw an exception you loose all stack trace information of what happened prior to the newly thrown exception. The problem is that you have all your code in the same files and you are having trouble reading and correctly comparing the information in each stacktrace.
Build the following code, making sure that each class is in a diferent .cs file. Run it and compare both printed stack traces and you will see that throwing loses information:
//Foo.cs
public class Foo
{
public void Crash() => throw new Exception();
}
//Blah.cs
public class Blah
{
public void CrashAndThrow()
{
var foo = new Foo();
try
{
foo.Crash();
}
catch (Exception ex)
{
throw ex;
}
}
public void CrashAndReThrow()
{
var foo = new Foo();
try
{
foo.Crash();
}
catch
{
throw;
}
}
}
//Program.cs
class Program
{
static void Main(string[] args)
{
var bla = new Blah();
try
{
bla.CrashAndThrow();
}
catch (Exception ex)
{
Console.WriteLine("Throw:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
}
try
{
bla.CrashAndReThrow();
}
catch (Exception ex)
{
Console.WriteLine("Rethrow:");
Console.WriteLine(ex.StackTrace);
}
Console.ReadLine();
}
}
The output of this program is, in my computer:
Throw:
at SOStuff.Alpha.Blah.CrashAndThrow() in ...\SOStuff\Blah.cs:line 16
at SOStuff.Program.Main(String[] args) in ...\SOStuff\Program.cs:line 13
Rethrow:
at SOStuff.Alpha.Foo.Crash() in ...\SOStuff\Foo.cs:line 7
at SOStuff.Alpha.Blah.CrashAndReThrow() in ...\SOStuff\Blah.cs:line 24
at SOStuff.Program.Main(String[] args) in ...\SOStuff\Program.cs:line 24
As you can see, when you throw, all information of the orignal exception thrown in Foo is lost.
The general rules I apply are:
If you can't handle it, don't catch it
If you can't handle it, but you need to catch it in order to clean up, log information, or whatever, rethrow it.
If you can't handle it but you can't allow sensistive or non appropiate information in the exception reach the consumer, then throw a new one with enough information that allows correct debugging later on.
If you can handle it, then handle it.
99% of the time, I apply rule #1.

Object not set to a reference

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

C# Catch re-throw/propagation for a specific exception type

I am trying to propagate to my UI the GatewayConnectionFailedException as you can see. I want this code to catch everything except that exception which I want the presentation layer to catch to notify the user that the database was the problem so he can go and fix it. My problem is that when I throw it the first time then I get GatewayConnectionFailedException not handled by user code on the GatewayException catch clause.
Its also important to note the the GatewayConnectionFailedException extends GatewayException which extends Exception. Is there something I am missing or will I have to move all the catch to the presentation layer ?
try
{
something();
}
catch (GatewayConnectionFailedException gcfe)
{
throw;
}
catch (GatewayException ge)
{
if (ge.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to a data gateway error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", ge);
}
catch (Exception e)
{
if (e.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", e);
}
Stupid question... is your UI code try-catching in it's call to this layer? Something has to handle that second throw...
In a nutshell, it sounds like you're trying to do this:
using System;
namespace ConsoleApplication1
{
class ExceptionA : Exception
{
public override string Message
{
get
{
return "Exception A";
}
}
}
class ExceptionB : ExceptionA
{
public override string Message
{
get
{
return "Exception B";
}
}
}
class Program
{
static void Main(string[] args)
{
try
{
DoThing();
}
catch (Exception ex)
{
Console.WriteLine("Caught in 'UI' code: " + ex.Message);
}
}
static void DoThing()
{
try
{
throw new ExceptionB();
}
catch (ExceptionB ex)
{
Console.WriteLine("Caught B");
throw;
}
catch (ExceptionA ex)
{
Console.WriteLine("Caught A");
}
catch (Exception ex)
{
Console.WriteLine("Caught Generic");
}
}
}
}
Which yields this output:
Caught B
Caught in 'UI' code:
Exception B
Press any key to continue...
It just seems like you don't have anything catching the 2nd thrown exception, which is why it's "unhandled." If we comment out the try-catch in main, we end up with an unhandled exception:
static void Main(string[] args)
{
//try
//{
DoThing();
//}
//catch (Exception ex)
//{
//Console.WriteLine("Caught in 'UI' code: " + ex.Message);
//}
}
Yielding the following output:
Caught B
Unhandled Exception: ConsoleApplication1.ExceptionB: Exception B
at ConsoleApplication1.Program.DoThing() in C:\Users\Giovanni\AppData\Local\T
emporary Projects\ConsoleApplication1\Program.cs:line 50
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Giovanni\AppDa
ta\Local\Temporary Projects\ConsoleApplication1\Program.cs:line 33
Press any key to continue . . .
One item to not although this might not fix the exception, if you are catching and rethrowing the exception use this code instead:
catch (GatewayConnectionFailedException)
{
throw;
}
this way the stacktrace reflects the programs journey more accurately. It may not solve the issue though.
Hard to tell what is missing without full picture, but one important thing that you should throw exceptions in different way. The syntax should be
throw;
you will have full stacktrace. More info.
Catching of GatewayConnectionFailedException should solve your problem and in catch block just do throw, don't throw the exception object. Answer by Andy is correct.
Secondly I'm assuming GatewayConnectionFailedException inherits from GatewayException.
Select catch sequence in ascending of order of inheritance, child class should come first and then base class.
catch(Child){}
catch(Base){}
catch(Exception) {} //Base class for all exceptions
to start your try catch is redundant. the first catch will handle GatewayConnectionFailedException the remaining catches will never be of type GatewayConnectionFailedException because they were handled by the first catch. so the code can be simplified to
try
{
something();
}
catch (GatewayConnectionFailedException)
{
throw;
}
catch (GatewayException e)
{
_logger.Error(e.Message, e);
}
Now how the UI will handle this depends on how you handle the exception. if you just throw the exception, then you need a try catch in the presentation layer as well. However if the return type of this layer returned an object like
class Result<T>
{
T Value {get;set;}
Exception Error {get;set;}
}
Then you could simply process the type without need try/catch in the presentation layer.
Also worth noting is what you are catching and why you are trying to catch it. typically you don't want to catch Exception except at the application layer where you log the error and fail. Exceptions should be exceptional, and therefore only catch exceptions you expect can happen and why they may happen. otherwise let them bubble up.
Instead of using throw exceptionName try only throw.
Edit 1:
Try catching all exceptions in the same block, then throw back the exception only if it's the GatewayConnectionFailedException
try
{
something();
}
catch (Exception e)
{
if (e.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", e);
}

Resuming execution of code after exception is thrown and caught

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);
}
}
}

Categories