Why using blocks swallow exceptions? - c#

I recently ran into a problem with exception handling in using statement. The problem is that exceptions which throws inside 'using block' could swallowed, for example look at code:
class DisposableObject : IDisposable
{
public void Dispose()
{
throw new Exception("dispose");
}
}
class Program
{
static void Main()
{
try
{
using (var obj = new DisposableObject())
{
throw new Exception("using");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
In this example you will see 'dispose' in output, first exception will be ignored and you will never know about it. After some searching i found article https://msdn.microsoft.com/en-us/library/aa355056(v=vs.110).aspx about common mistakes about use using block. But my question isn't about how to avoid exception swallowing, i' want to know why MS decided to unwrap using block to
try
{
...
}
finally
{
}
and not the otherwise, for example they could unwrap using to something like this:
//this code prevents exception swallowing
try
{
...
}
catch (Exception ex)
{
try
{
if (obj != null)
obj.Dispose();
}
catch (Exception disposeEx)
{
throw new AggregateException(ex, disposeEx);
}
throw;
}
if(obj != null)
obj.Dispose();

Because AggregateException didn't exist when the using() block was created.
Also because Dispose() is really not supposed to throw.
Finally, because there are subtle semantic differences between your example and a finally block, with regard to exception filters, stack unwinding, and critical regions.

Related

Specific exceptions handling

Is there any reason to use specific expetion classes MyException1 and MyException2 in this case?
public static void Main()
{
try
{
TestMethod();
}
catch(Exception ex)
{
Console.Writeline(ex);
}
}
private static void TestMethod()
{
// This method can throw Exception1 and Exception2
}
public class MyException1 : Exception {}
public class MyException2 : Exception {}
I know that it makes sense in case when we have several catch blocks for each exception type. But in this case MyException1 and MyException2 are similar empty. These throwed exceptions will be casted to Exception class in the Main method. Maybe is it better not to create two similar Exception classes with such handling?
The concept behind a catch block is that you handle the exception. If a certain type of exception requires a certain type of handling, it is helpful when that exception has its own class, so it can have its own catch block.
For example, if MyException1 can be safely swallowed while MyException2 is fatal, you could write:
try
{
DoSomethingHard();
}
catch (MyException1 exception1)
{
_log.Write("Warning: small exception, no worries. {0}", exception1.Message);
continue;
}
catch (MyException2 exception2)
{
_log.Write("Fatal: big exception, gotta bail out now. {0}", exception2.Message);
break;
}
Exceptions should be wide rather than deep. Have a different exception for each, erm... exception.
Your example doesn't really show a good example. Perhaps if it was more like:
public static void Main()
{
try
{
TestMethod();
}
catch(Exception ex)
{
Console.Writeline(ex);
}
}
private static void TestMethod()
{
if(..bad configuration)
throw new ConfigurationException("configuration item");
if(missing file)
throw new FileMissingException("filename");
// This method can throw Exception1 and Exception2
}
public class ConfigurationException : Exception {}
public class FileMissingException : Exception {}
If you are using ASP.NET, its so common that you create and use your own Exception handler, in that case, you can to consider specific behavior for each exception in only one method (not catch block in every error prone code blocks), look at this simple example:
public class MyExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
if (context.Exception is SqlException)
{
//do something...
}
else if (context.Exception is HttpListenerException)
{
//do something...
}
else
{
//do something else...
}
}
}

Exit the function/method if an exception occurs

I'm trying to find a code to exit the whole method if an exception occurs in a sub method. I tried adding return in catch section of Subfunction() but the process will continue to Thirdfunction()
public static void Mainfunction()
{
try
{
//some code
//some code
Subfunction();
ThirdFunction();
}
catch(Exception ex)
{
//write to log
}
}
public static void Subfunction()
{
try
{
//some code
//some code
}
catch (Exception ex)
{
//write to log
}
}
So basically if an error occured in the Subfuntion() I want to stop the process from the Mainfunction() without continuing to the ThirdFunction(). Any help will be highly appreciated. Thanks
if an error occured in the Subfuntion() I want to stop the process
from the Mainfunction()
The simplest way to remove try/catch in your method Subfunction
If you want to keep the try/catch in this method, (for logging or something), rethrown exception
public static void Main()
{
try
{
Subfunction();
Thirdfunction();
}
catch(Exception ex)
{
}
}
public static void Subfunction()
{
try
{
throw new AccessViolationException();
}
catch (Exception ex)
{
throw;
}
}
There are basically two sets of possible solutions: With use of Exceptions and without.
With the use of exceptions, I'd recommend to just let it bubble up , as I've already said in comments.
Then you can rethrow:
try {
// exception here
}
catch(Exception ex)
{
throw;
// Attention: this is _different_ from "throw ex" !!
}
Pay attention here:
You can also use the throw e syntax in a catch block to instantiate a new exception that you pass on to the caller. In this case, the stack trace of the original exception, which is available from the StackTrace property, is not preserved.
See throw (C# Reference) (emphasis by me)
Coming over from Java myself, this is something people like myself will trip over during transitioning from Java to .Net. So if you got "java guys" new on the team: don't be harsh on them, just point them to the docs.
You can wrap:
try {
// exception here
}
catch(Exception inner)
{
throw new MyCustomException( "Some custom message", inner);
}
BTW: It is generally not a good idea to catch Exception. Most of the time you'd want to catch specific exceptions that you can actually handle.
The other class of solutions is without bubbling up exceptions:
Return value:
public static bool Subfunction()
{
bool success = true;
try
{
//some code
//some code
}
catch (Exception ex)
{
// TODO write error log!
success = false;
}
return success;
}
Or with return or error codes:
// DO NOT USE MAGIC NUMBERS !
private static readonly int SUCCESS_INDICATOR = 0;
private static readonly int ERROR_INDICATOR = 1;
// TODO DOCUMENT which errorcodes can be expected and what they mean!
public static int Subfunction()
{
int success = SUCCESS_INDICATOR;
try
{
//some code
//some code
}
catch (Exception ex)
{
// TODO write error log!
success = ERROR_INDICATOR;
}
return success;
}
Especially with "C-Guys" on the team you may stumble across this one. (No offense - just my experience)
Or with a state object ...
public static void Mainfunction()
{
try
{
//some code
//some code
ISuccessIndicator success = new ISIImplementation();
Subfunction( success );
if( !succes.HasException )
{
ThirdFunction();
}
else
{
// handle exception from Subfunction
}
}
catch(Exception ex)
{
//write to log
//Exceptions from ThrirdFunction or "else" branch are caught here.
}
}
public static void Subfunction( ISuccessIndicator result )
{
try
{
//some code
//some code
}
catch (Exception ex)
{
result.HasException=true;
result.Exception = ex;
}
}
public interface ISuccessIndicator
{
Exception Exception {get; set;}
bool HasException {get; set;}
}
And if you are really crazy you could ...
public static void Mainfunction()
{
try
{
//some code
//some code
Exception ex = null;
Subfunction( ref ex );
if( ex == null ) // or more modern: ( ex is null )
{
ThirdFunction();
}
else
{
// handle exception from Subfunction
}
}
catch(Exception ex)
{
//write to log
//Exceptions from ThirdFunction or "else" branch caught here.
}
}
public static void Subfunction( ref Exception outEx )
{
try
{
//some code
//some code
}
catch (Exception ex)
{
outEx = ex;
}
}
Please mind, that I in no way would encourage using the latter. But it is possible ... and OP asked for possibilities.
Disclaimer: All snippets untested. Who finds errors can keep them (but please write a comment, so I can fix them).

What's the point of passing ExceptionDispatchInfo around instead of just the Exception?

I understand the value of ExceptionDispatchInfo.Capture(e).Throw() (preserves the original stack trace), but what's the advantage of using Capture early and passing the ExceptionDispatchInfo around vs. just passing the caught Exception around?
As a concrete example, comparing
static Exception CaptureException(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return e;
}
}
public void Test1()
{
ExceptionDispatchInfo.Capture(CaptureException(
() => throw new IOException("Test")))
.Throw();
}
with
static ExceptionDispatchInfo CaptureDispatchInfo(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return ExceptionDispatchInfo.Capture(e);
}
}
public void Test2()
{
CaptureDispatchInfo(() => throw new IOException("Test")).Throw();
}
, both give essentially the same stack traces (It's similar for an async variation of this.). So, I don't really get why the ExceptionDispatchInfo class exists at all, rather than just a combined ExceptionDispatchInfo.Capture(e).Throw() method.
You're assuming that exceptions are immutable. This is not the case - an exception's StackTrace changes when it's re-thrown.
The purpose of ExceptionDispatchInfo.Capture is to capture a potentially mutating exception's StackTrace at a point in time:
void Foo() => throw new InvalidOperationException ("foo");
Exception original = null;
ExceptionDispatchInfo dispatchInfo = null;
try
{
try
{
Foo();
}
catch (Exception ex)
{
original = ex;
dispatchInfo = ExceptionDispatchInfo.Capture (ex);
throw ex;
}
}
catch (Exception ex2)
{
// ex2 is the same object as ex. But with a mutated StackTrace.
Console.WriteLine (ex2 == original); // True
}
// So now "original" has lost the StackTrace containing "Foo":
Console.WriteLine (original.StackTrace.Contains ("Foo")); // False
// But dispatchInfo still has it:
try
{
dispatchInfo.Throw ();
}
catch (Exception ex)
{
Console.WriteLine (ex.StackTrace.Contains ("Foo")); // True
}
ExceptionDispatchInfo is used to preserve the stack trace after an Exception is thrown, allowing you to catch that exception, not throwing it immediately (as part of a catch), and to raise such exception on a later point in the future.
I found a good example of this on
https://thorarin.net/blog/post/2013/02/21/Preserving-Stack-Trace.

using block swallowing exceptions

I have
void foo1()
{
using(...){...}
}
void foo2()
{
using(...){...}
}
void foo3()
{
using(...){...}
}
and I have
void foo()
{
...
backgroundWorker.DoWork += (s, ev) =>
{
try
{
foo1();
foo2();
foo3();
}
catch (Exception ex)
{
// log ex
}
};
...
}
and I just read that using blocks swallow exceptions. It there an elegant way to handle exceptions from foo1(), foo2() and foo3() in foo(). I don't want to have a try/catch inside of each using block in the methods. I did stumble into this post where an extension method is suggested but I'm just checking to see if there is anything better.
FYI, Network disconnection causes the logic inside the using block to throw an exception and that's what I'm trying to handle in one common place.
Thanks,
I think I understand the confusion. Here's some pseudo-code (it may actually execute?) explaining your scenario more simply:
public class Foo
{
public void DoStuff()
{
using (var x = new Thing())
{
throw new ApplicationException("This code breaks");
}
}
private class Thing : IDisposable
{
public override Dispose()
{
throw new ApplicationException("Help, I can't dispose!");
}
}
}
This code can be thought of as the same as this code:
public class Foo
{
public void DoStuff()
{
var x = new Thing();
try
{
throw new ApplicationException("This code breaks");
x.Dispose();
}
catch (Exception err)
{
x.Dispose();
rethrow;
}
}
private class Thing : IDisposable
{
public override Dispose()
{
throw new ApplicationException("Help, I can't dispose!");
}
}
}
By using a using block, you are essentially saying, "No matter what you do, execute Dispose() on this object before moving on." However, the using block doesn't gracefully handle the case when Dispose() fails. Because of this, it never gets around to throwing the inside exception because there was another exception that pre-empted it, even if it occurred afterwards.
Does this make sense? Did I even answer your question? I'm not sure if you're looking for help understanding this or what.
My fear is that Microsoft went down the same rabbit hole here as they did with WCF.
See Avoiding Problems with the Using Statement.
Maybe they should follow their own guidelines.
In almost every (other) case a using block is a best practice.
Youcan try this code to bubble-up and exception from a using statement
Exception exc = null;
using (var x = new object())
{
try
{
// do something x, that causes an exception to be thrown
}
catch(Exception ex) { exc = ex; } // bubble-up the exception
}
if(exc != null) { throw exc; } // throw the exception if it is not null

Return catched exception inside a class method to the caller

I am making a class for using in a winforms application in VC#
My question is how to return a catched exception to the caller out of the class? Take this as an example:
Public Class test
{
private int i = 0;
public test() { }
public SetInt()
{
try
{
i = "OLAGH"; //This is bad!!!
return i;
}
catch (Exception ex)
{
throw ex;
}
}
}
And imagine calling this method in another place while referencing to this class. Is that a good idea? Or how it should be done?
You have several options.
You could not handle the exception at all :
public SetInt()
{
i = "OLAGH"; //This is bad!!!
return i;
}
Then the caller will need to handle the exception.
If you want to handle the exception you can catch the error and handle it.
public SetInt()
{
try
{
i = "OLAGH"; //This is bad!!!
return i;
}
catch (FailException ex)
{
return FAIL;
}
}
Note that it is bad practice to just catch the base Exception class. You should anticipate which errors may occur and try to handle them. Unanticipated errors and the result of bugs and should make a big noise so that you can be alerted to other problems and fix them.
If you want to raise your own kind of exception, you could do :
public SetInt()
{
try
{
i = "OLAGH"; //This is bad!!!
return i;
}
catch (FailException ex)
{
throw new SetIntFailException ( ex );
}
}
Then it is the callers responsibility to handle the SetIntFailException rather than a CastFailException or whatever hundreds of other kind of exceptions your code may throw..
If you want the caller to handle the exception, but you have some clean up you want to do, you can use finally :
public SetInt()
{
try
{
i = "OLAGH"; //This is bad!!!
return i;
}
finally
{
// Cleanup.
}
}
The code in the finally block will always be called, even when there is an exception, but the error still gets raised to the caller.
I am assuming that in your real code, it will at least compile! ;-)
In the first place, the code won't compile.
public class test
{
private int i = 0;
public test(){}
public SetInt(object obj)
{
try
{
i = (int) obj;
return i;
}
catch(exception ex)
{
throw; // This is enough. throwing ex resets the stack trace. This maintains it
}
}
}
If you want to throw an exception do this:
throw new Exception ("My exception");
You can make a class derived from Exception if you want to hold some exception specific details.

Categories