The mystery of the twin exceptions - c#

Here's an interesting question. I have a system that attempts to run some initialization code. If it fails, we call the deinitializer to clean everything up.
Because we call the deinitializer in exception handling, we run the risk that both initialize and deinitialize will fail, and hypothetically, it now seems that we have to throw two exceptions.
It seems pretty unlikely that we will, though. So what happens and what should the code do here?
try { /* init code here */ }
catch (Exception ex)
{
try
{
_DeinitializeEngine();
}
catch (Exception ex2)
{
throw new OCRException("Engine failed to initialize; ALSO failed to deinitialize engine!", ex2);
}
finally
{
throw new OCRException("Engine failed to initialize; failed to initialize license!", ex);
}
}

You shouldn't throw in the Finally block. Instead, use the InnerException to add information in the throw.
Update
What you have to do is to catch and rethrow with the "history" of exception, this is done with InnerException. You can edit it when bulding a new exception. This is a code snippet I just wrote to illustrate the idea that I explain in all the comments below.
static void Main(string[] args)
{
try
{
principalMethod();
}
catch (Exception e)
{
Console.WriteLine("Test : " + e.Message);
}
Console.Read();
}
public static void principalMethod()
{
try
{
throw new Exception("Primary");
}
catch (Exception ex1)
{
try
{
methodThatCanCrash();
}
catch
{
throw new Exception("Cannot deinitialize", ex1);
}
}
}
private static void methodThatCanCrash()
{
throw new NotImplementedException();
}
No need to use double throw with finalize. If you put a break point at the Console.WriteLine(...). You will notice that you have all the exception trace.

If your clean up code is failing and you cannot leave the application in a clean and known state I would let the exception go unhandled (or catch it with the UnhandledException event to log it) then close the application.
Because if you can't handle the first exception, what point is there in catching the second exception?

If I understand your problem correctly, here's what I would have done:
try { /* init code here */ }
catch (Exception ex)
{
// Passing original exception as inner exception
Exception ocrex = new OCRException("Engine failed to initialize", ex);
try
{
_DeinitializeEngine();
}
catch (Exception ex2)
{
// Passing initialization failure as inner exception
ocrex = new OCRException("Failed to deinitialize engine!", ocrex);
}
throw ocrex;
}

You have two possible exception conditions: one in which the first method failed, and one in which both methods failed.
You're already defining your own exception class. So create another (or extend the first) with a RelatedException or PriorException property. When you throw the exception in the second case, save a reference to the first exception in this property.
It's up to the exception handler that catches this exception to figure out what to do with the second exception.

Related

Can I delete the e from catch block of try-catch?

catch (HttpAntiForgeryException e)
{
throw new HttpAntiForgeryException("Forgery Exception");
}
When I build the project, there is a warning said: The variable 'e' is declared but never used.
Is that because the e is not necessary?
Yes. You can just simply write
catch (HttpAntiForgeryException)
{
throw new HttpAntiForgeryException("Forgery Exception");
}
But, you are rethrowing same type of exception. You can also simply delete this catch block.
It is no necessary if you don't want to do anything with the exception, in your case you are throwing custom message so its fine to use like this :
catch
{
throw new HttpAntiForgeryException("Forgery Exception");
}
or like this :
// For specific exception
catch (HttpAntiForgeryException)
{
throw new HttpAntiForgeryException("Forgery Exception");
}
But you will not get any information regarding this exception, like error message, stack-Trace, inner exception etc.. I prefer you to handle the exception in Catch, Or properly log them for developer's reference
It's because You have not used the Variable e within any where of the catch block. You can easily catch that exception so you will get better understanding of the root cause of your exception than throwing a new exception.
catch (HttpAntiForgeryException e)
{
Console.WriteLine(e.Message); // Console.Writeline or whichever way you want
}

Throwing exception after modifying its Dictionary

The following is my code in C#:
catch(Exception ex)
{
ex.Data.Add("VarName", "object");
throw;
}
Question: doing above, am I going to lose the entry I am adding to Data dictionary? -->as in my opinion, I am rethrowing the exception caught in the catch statement, and it does not have the added Dictionary record from the next line yet.
Should above code instead be:
catch(Exception ex)
{
ex.Data.Add("VarName", "object");
throw ex;
}
but in this case, I don't want to reset the stack trace.
Searched this all over the web and on SO, but no luck.
TIA!
Your initial code should work just fine. You should not lose the dictionary entry.
[EDIT]: Elaboration.
Let's take the following example code:
using System;
class Program
{
static void Main()
{
Change();
Replace();
Inner();
}
static void Change()
{
try {
try {
throw new Exception("This is a message");
} catch (Exception e) {
e.Data.Add("foo", "bar");
throw;
}
} catch (Exception e) {
System.Diagnostics.Trace.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(e.Data["foo"]);
}
}
static void Replace()
{
try {
try {
throw new Exception("This is a message");
} catch (Exception e) {
e = new Exception("Different message", e);
e.Data.Add("foo", "bar");
throw;
}
} catch (Exception e) {
System.Diagnostics.Trace.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(e.Data["foo"]);
}
}
static void Inner()
{
try {
try {
throw new Exception("This is a message");
} catch (Exception e) {
e.Data.Add("foo1", "bar1");
e = new Exception("Different message", e);
e.Data.Add("foo2", "bar2");
throw e;
}
} catch (Exception e) {
System.Diagnostics.Trace.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(e.Data["foo2"]);
System.Diagnostics.Trace.WriteLine(e.InnerException.Message);
System.Diagnostics.Trace.WriteLine(e.InnerException.Data["foo1"]);
}
}
}
When throwing an Exception, what is really thrown is a reference to an Exception object. That reference is what is caught and rethrown. Modifying the underlying object is fine. This is what your initial code does, and what the Change method in my example does.
In the Replace method we modify not the object, but the reference itself. We make it point to a brand new Exception object with a different message and to top it off we also add some data. All this stuff is lost, though, because throw without arguments rethrows the original reference.
Should the need arise to use the second case, you can keep track of your stack trace by including the original exception as InnerException, like I did in the Inner method.

Unhandled exception when calling throw

catch (OracleException e)
{
Cursor.Current = Cursors.Default;
_instance = null;
if (e.ErrorCode == -2147483648) // {"ORA-01017: invalid username/password; logon denied"}
{
throw new Exception("Nepravilno ime uporabnika ali geslo");
}
else
{
throw new Exception("Ne morem se povezati na podatkovno bazo. Preveri povezavo!");
}
}
but i always get Unhandled exception. Why?
At the risk of stating the obvious... Because you're not catching the Exception you throw in your catch block? Or, perhaps, something else is being thrown in the try block that isn't an OracleException.
What are you expecting to happen?
Just to be totally clear (to make sure that we're on the same page), an exception that's thrown but never caught will result in an unhandled exception (by definition). Throwing an exception from within a catch block is identical to throwing it from anywhere else; there still needs to be a try-catch somewhere to catch it. For example, this exception will be caught:
try {
throw new Exception("Out of cheese error"); // Caught below
}
catch (Exception) { }
But this one results in a new exception being propogated:
try {
throw new Exception("Out of cheese error"); // Caught below
}
catch (Exception) {
throw new Exception("418: I'm a teapot"); // Never caught
}
And this code catches both exceptions:
try {
try {
throw new Exception("Out of cheese error"); // Caught in inner catch
}
catch (Exception) {
throw new Exception("418: I'm a teapot"); // Caught in outer catch
}
}
catch (Exception e) {
Console.WriteLine(e.Message); // "418: I'm a teapot"
}
Your code does not in anyway swallow an exception. All it does is catch one type of exception and throw another type of exception. If you have an unhandled exception before you write this code, you will still have one after you write it.
--UPDATE --
Referring to your comment to another answer, if you want to display a message and stop executing code then try:-
catch (OracleException e)
{
Cursor.Current = Cursors.Default;
_instance = null;
if (e.ErrorCode == -2147483648) // {"ORA-01017: invalid username/password; logon denied"}
{
MessageBox.Show("Nepravilno ime uporabnika ali geslo");
}
else
{
MessageBox.Show("Ne morem se povezati na podatkovno bazo. Preveri povezavo!");
}
// this exits the program - you can also take other appropriate action here
Environment.FailFast("Exiting because of blah blah blah");
}
I assume you call hierarchy look like this:
Main
|-YourMethod
try {}
catch (OracleException) {throw new Exception("blah blah")}
So you see, the OracleException which occured in YourMethod is being caught by catch block, but then you throw a new one which goes into Main, where nothing handles it. So you should add an exception handler on the previous level.
Also, do not hide the original OracleException, throw your exception this way throw new Exception("your message", e). This will preserve the call stack.
Because you're only handling the OracleException. Nothing is handling the Exception() you are throwing.
You're catching the OracleException which means you're prepared to handle it - what does handling it mean to you? Logging it and moving on? Setting some state and moving on? Surely, you don't want to pop up gui in a data access component right? If you're not prepared to handle it, let it bubble up and handle it at an outer layer.
You also shouldn't throw exceptions of type Exception. Create your own strongly typed exceptions so they can be handled, or, simply log and call throw; which rethrows the original.
If you throw a new type of exception ensure you're passing the original exception as the inner exception to ensure you're not hiding details.
I did a write up on some best practices with C# exceptions:
Trying to understand exceptions in C#
Hope that helps

C# try..catch - redirecting error handling flow from one catch to the next

I have a try..catch block that looks like this:
try
{
...
}
catch (IOException ioEx)
{
...
}
catch (Exception ex)
{
...
}
I'd like to handle just a certain kind of IOException, namely a sharing violation (Win32 0x20). Other IOExceptions and all other Exception descendants should be handled generally by the second catch-all catch.
Once I know that the IOException is not a sharing violation, how can I cleanly redirect the error handling flow to the general catch? If I rethrow in catch (IOException) the second catch does not invoke. I know I can nest try..catches but is there a cleaner way?
EDIT: On factoring-out handler logic
Factoring repeated code in methods will surely work, but I noticed that in general when you use factored methods for exception handling it tends to have subtle problems.
First of all, a catch clause has direct access to all of the local variables prior to the exception. But when you "outsource" exception handling to a different method then you have to pass the state to it. And when you change the code so does the handler method's signature changes, which might be a maintainability issue in more complicated scenarios.
The other problem is that program flow might be obscured. For example, if the handler method eventually rethrows the exception, the C# compiler and code analyzers like Resharper don't see it:
private void Foo()
{
string a = null;
try
{
a = Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
HandleException(ex, a); //Note that we have to pass the "a"
System.Diagnostics.Debug.Print(
"We never get here and it's not obvious" +
"until you read and understand HandleException"
);
...!
}
}
static void HandleException(Exception ex, string a)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw (ex); //Rethrow so that the application-level handler catches and logs it
}
VS
private void Bar()
{
string a = null;
try
{
a = System.IO.Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw; //Rethrow so that the application-level handler catches and logs it
System.Diagnostics.Debug.Print(
"We never get here also, but now " +
"it's obvious and the compiler complains"
);
...!
}
}
If I want to avoid these kind of (minor) problems then it seems that there is no cleaner way than nesting try..catch blocks, as Hank pointed out.
Just factor the handling logic into a separate method.
try
{
...
}
catch (IOException ioEx)
{
if (sharing violation)
HandleSharingViolation();
else
HandleNonsharingViolation();
}
catch (Exception ex)
{
HandleNonsharingViolation();
}
Or test the exceptions yourself
catch (Exception ex)
{
if (ex is IOException && ex.IsSharingViolation()
HandleSharingViolation();
else
HandleNonsharingViolation();
}
No, you'll have to nest.
Once you are in 1 of the catch blocks, this 'try' is considered handled.
And I think it may make a lot of sense, "sharing violation" sounds like a special case that probably isn't so tightly coupled to the rest as you might be thinking. If you use nest try-catch, does the try block of the special case has to surround the exact same code? And of course it's a candidate to refactor out as a separate method.
Create Method to handle exception, pass the exception to that method , based on the type Handle the exception in the way you want.Call these method in both these blocks.
Use nested try catch blocks.
try
{
try
{
}
catch (IOException ioEx)
{
if (....)
else
throw;
}
}
catch
{
}
what about "finally"?
you can first set a 'variable' in the IOException block once you know the IOException is not sharing violation. Then, in your finally block, if that 'variable' is set, you proceed to do whatever you need to do.
Below impl. tested and confirmed.
bool booleanValue = false;
try
{
test1(); // this would thro IOException
}
catch (IOException e)
{
booleanValue = true; // whatever you need to do next
}
finally
{
if (booleanValue)
{
Console.WriteLine("Here");
}
}
Tryout this nested block
try
{
}
catch(Exception ioex)
{
try
{
}
catch(Exception ex)
{
}
}

Exception.Data and Exception Handling Questions

I have a couple questions about exceptions.
1) when you hit a catch block, swallowing means what exactly? I thought it was always rethrow or the existing exceptions is passed up to the next catch block.
2) If you add Exception.Data values to an excepction, I notice I have to do another throw; to grab that data futher up in another catch block later. Why?
Swallowing an exception means catching it and not doing anything useful with it. A common thing you might see is this:
try
{
DoSomeOperationThatMightThrow();
}
catch (Exception ex) // don't do this!
{
// exception swallowed
}
You usually don't want to catch a base Exception at all, it's better to catch and handle specific Exception types, and ideally you should only catch exception types that you can do something useful with at the level of code you're in. This can be tricky in complex applications, because you might be handling different errors at different levels in the code. The highest level of code might just catch serious/fatal exceptions, and lower levels might catch exceptions that can be dealt with with some error handling logic.
If you do catch an exception and need to rethrow it, do this:
try
{
DoSomething();
}
catch (SomeException ex)
{
HandleError(...);
// rethrow the exception you caught
throw;
// Or wrap the exception in another type that can be handled higher up.
// Set ex as the InnerException on the new one you're throwing, so it
// can be viewed at a higher level.
//throw new HigherLevelException(ex);
// Don't do this, it will reset the StackTrace on ex,
// which makes it harder to track down the root issue
//throw ex;
}
Swallowing an exception normally means having a handling block for the exception, but not doing anything in the block. For example:
try { 3/0; } catch DivideByZeroException { //ignore } //Note: I know this really wont' compile because the compiler is smart enough to not let you divide by a const of 0.
You have to rethrow because the first handler for an exception is the only one that will execute.
If you want the exception to bubble up you either don't handle it or you rethrow it. By the way, it's important to note that in .NET by just saying "throw" you'll preserve the stack trace. If you "throw Exception" you'll lose your stack trace.
Ok, you can handle the exception up to call stack you can do some thing like this:
public class A
{
public void methodA()
{
try
{
}
catch(Exception e)
{
throw new Exception("Some description", e);
}
}
}
public class B
{
public void methodB()
{
try
{
A a = new A();
a.methodA();
}
catch(Exception e)
{
//...here you get exceptions
}
}
}

Categories

Resources