I know this question has been asked quite a few times but i still don't understand what the proper order should be.
If you want to catch an exception in the objects creation you have to put the try and catch outside of the using statement:
try { using... } catch (Exception e) { }
And if you want to catch an exception after the objects creation then:
using(...) { try {...} catch (Exception e) {} }
But what if you want to catch both during and after the objects creation? Would it be:
try { using(...) { try {...} catch (Exception e) {} } } catch (Exception e) { }
Or would it be better to just use a try, catch, and a finally with a dispose?
The using block is more about the Disposal than the creation. As mentioned in the documentation, it's a shortcut to this code:
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
This is the definition of a try-catch block
The try block contains the guarded code that may cause the exception.
The block is executed until an exception is thrown or it is completed
successfully.
So from there, the strategy is up to you. This piece of code:
try
{
using(Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
}
will be translated as:
try
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
As you can see, you are catching exceptions cause by the constructor, the block and also the Dispose.
Whereas this:
using(Font font1 = new Font("Arial", 10.0f))
{
try
{
byte charset = font1.GdiCharSet;
}
}
will be translated as:
Font font1 = new Font("Arial", 10.0f);
try
{
try //This is your try
{
byte charset = font1.GdiCharSet;
}
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
So here you will catch exception cause neither by the constructor nor the Dispose.
Any exception thrown within the context of your try block will be handled by the corresponding catch block. You can have, in this instance, one try block that can catch exceptions from multiple sources and handle them as you wish. Consider the following code...
try
{
using(var con = DataService.GetSomethingDisposable()) // Possible InvalidOperationException();
{
// Do what you need here
// Possible Exception here
}
}
catch(InvalidOperationException ex)
{
// Handle as you will
}
catch(Exception ex) // Catch any other exception
{
// Handle as you will
}
So with this you can catch and respond to any exception that arises with the same try...catch block.
MSDN Reference https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement
When the lifetime of an IDisposable object is limited to a single
method, you should declare and instantiate it in the using statement.
The using statement calls the Dispose method on the object in the
correct way, and (when you use it as shown earlier) it also causes the
object itself to go out of scope as soon as Dispose is called. Within
the using block, the object is read-only and cannot be modified or
reassigned.
Option 1 would catch both scenarios:
try { using() } catch (Exception) {}
If you create a new object which throws an exception on initialisation, the exception will be caught in your catch block.
Equally, if something inside your using block throws an exception, that will also be caught in the catch block.
An exception will always bubble up to the first catch block which is capturing that type of exception. If there's nothing to catch the exception, it'll likely bubble all the way up and terminate your application
Related
Ok, as far as I understand, try/catch blocks try an operation and catch blocks catch exceptions. The more specific exceptions go up top, the more generic towards the bottom of the series of catch blocks. In the following code, I implement try/catch, everything works fine.
As far as I understand, a finally block always executes. Some people have argued that there is no purpose to finally block, because if there is an exception or there isn't, the code after the last catch block gets executed anyways.
However, the argument against this is that if there is an exception thrown in a catch block, there are no subsequent catch blocks to catch that exception. So by putting resource cleanup code in a finally block, you ensure that resources will be released in the event that an exception is thrown in a catch block.
Which is why the following code puzzles me. I throw an exception in the first catch block and the finally block never executes. Why?
*Please note that there is indeed an exception thrown while creating myStreamReader, as the file is actually called generic.txt and is misspelled with purpose, in order to throw the initial exception.
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreadReader.ReadToEnd());
}
catch(FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw new Exception();
}
catch(Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
if(myStreamReader != null)
{
myStreamReader.Close();
}
Console.WriteLine("Closed the StreamReader.");
}
VIDEO:
The issue with this block of code originates in this video, at the 27:20 mark:
https://www.youtube.com/watch?v=WxdSb3ZCWYc&list=PLAC325451207E3105&index=41
The guy directly declares that an Exception that occurs in a catch block will not prevent the finally block from executing. I am seeing that it does.
If that new exception is completely unhandled, the entire process is torn down, and the finally block never gets to run.
If there's some other exception handler at a higher level, or an unhandled exception handler has been installed, the finally block does run.
This sample does show "Closed the StreamReader":
static void Main()
{
try
{
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreamReader.ReadToEnd());
}
catch (FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw new Exception();
}
catch (Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
if (myStreamReader != null)
{
myStreamReader.Close();
}
Console.WriteLine("Closed the StreamReader.");
}
}
catch
{
}
Console.WriteLine("Done");
Console.ReadLine();
}
Unhandled exception handlers can be registered in the AppDomain.UnhandledException event.
Your understanding is not correct. See try-finally.
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
So finally does executed if you return for instance out of a try block, but not if you throw from a catch block.
However, if the exception is unhandled, execution of the finally block
is dependent on how the exception unwind operation is triggered. That,
in turn, is dependent on how your computer is set up.
Assuming the file is not found, it would first catch the FileNotFoundException:
catch(FileNotFoundException error)
{
Console.WriteLine(error.Message);
Console.WriteLine();
throw new Exception();
}
This writes a message to the console, and then throws a new Exception. This exception however, is unhandled and will halt execution. If you throw an exception from within a Catch block, it will not be caught by any subsequent blocks.
The solution is to handle the exception appropiately instead of throwing a new one. If the file was not found, then act upon it, e.g. let the user choose another file, create the file, etc.
use throw instead and try this. When you throw a new exception, the actual exception will be lost. But when you use just throw it will throw the actual exception which is FileNotFoundException.
StreamReader myStreamReader = null;
try
{
myStreamReader = new StreamReader("c:\\genneric.txt");
Console.WriteLine(myStreadReader.ReadToEnd());
}
catch(FileNotFoundException Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
throw;
}
catch(Exception Error)
{
Console.WriteLine(Error.Message);
Console.WriteLine();
}
finally
{
Console.WriteLine("Closing the StreamReader.");
try{
if(myStreamReader != null)
{
myStreamReader.Close();
}
} catch(Exception e) { Console.WriteLine(e.ToString()) };
}
}
I have code that attempts a type conversion. If it fails, I want to try something else, and if that also fails, then rethrow the original exception attempted by the first conversion. The problem is that the only way I know of to rethrow is to have 'throw;' sitting at the end of the catch block. What happens when I only want the rethrow to happen from within another catch block?
try
{
valueFromData = Convert.ChangeType(valueFromData, pi.PropertyType);
}
catch(InvalidCastException e)
{
Debug.WriteLine(String.Concat("Info - Direct conversion failed. Attempting to convert using String as an intermidiate type."));
try { valueFromData = Convert.ChangeType(valueFromData.ToString(), pi.PropertyType); }
catch { throw e; }
}
As you can see above, I have to use 'throw e;', which resets the call stack.
Only workaround I've though of so far is (imo) gross:
bool handled = true;
...
catch { handled = false; }
if( !handled ) throw;
There is no way to rethrow an exception from an outer catch block inside an inner catch block. The best way to achieve this pattern is to note whether or not the inner operation succeeded
catch (InvalidCastException e) {
bool threw = false;
try {
...
} catch {
threw = true;
}
if (threw) {
throw;
}
}
If you are intending to make multiple attempts at conversion then it certainly makes sense to use non-throwing operations where applicable so that you sidestep the problem entirely.
Supposing that's not possible for the sake of argument, the next step is to question the throw e; approach. In the example code you give, IMHO there is no problem at all if your throw resets the call stack. Once someone gets to the source code for this method (which the modified call stack would still point to), I think it's pretty obvious what's going on. So while resetting the call stack is always a questionable decision, in this particular case it should be allowed to happen because there would be no tangible drawback.
Finally, the workaround you mention is interesting as well as gross (agree on that!).
I tried the following and it seems to achieve your goal, when the 2nd exception occurs (in this case, the ArgumentException) it throws the first exception (InvalidCastException)
[TestMethod]
[ExpectedException(typeof(InvalidCastException))]
public void ReThrowException() {
var ret = false;
try {
ret = F1(1);
}
catch (InvalidCastException ex) {
try {
ret = F1(2);
}
catch (Exception e) {
Debug.WriteLine(e.Message);
throw ex;
}
}
}
private bool F1(int i) {
if (i == 1) {
throw new InvalidCastException();
} else {
throw new ArgumentException();
}
return false;
}
Hope this helps,
Alan.
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)
{
}
}
Which one:
using (var myObject = new MyClass())
{
try
{
// something here...
}
catch(Exception ex)
{
// Handle exception
}
}
OR
try
{
using (var myObject = new MyClass())
{
// something here...
}
}
catch(Exception ex)
{
// Handle exception
}
I prefer the second one. May as well trap errors relating to the creation of the object as well.
Since a using block is just a syntax simplification of a try/finally (MSDN), personally I'd go with the following, though I doubt it's significantly different than your second option:
MyClass myObject = null;
try
{
myObject = new MyClass();
//important stuff
}
catch (Exception ex)
{
//handle exception
}
finally
{
if (myObject is IDisposable)
{
myObject.Dispose();
}
}
It depends. If you are using Windows Communication Foundation (WCF), using(...) { try... } will not work correctly if the proxy in using statement is in exception state, i.e. Disposing this proxy will cause another exception.
Personally, I believe in minimal handling approach, i.e. handle only exception you are aware of at the point of execution. In other word, if you know that the initialization of a variable in using may throw a particular exception, I wrap it with try-catch. Similarly, if within using body something may happen, which is not directly related to the variable in using, then I wrap it with another try for that particular exception. I rarely use Exception in my catches.
But I do like IDisposable and using though so I maybe biased.
If your catch statement needs to access the variable declared in a using statement, then inside is your only option.
If your catch statement needs the object referenced in the using before it is disposed, then inside is your only option.
If your catch statement takes an action of unknown duration, like displaying a message to the user, and you would like to dispose of your resources before that happens, then outside is your best option.
Whenever I have a scenerio similar to this, the try-catch block is usually in a different method further up the call stack from the using. It is not typical for a method to know how to handle exceptions that occur within it like this.
So my general recomendation is outside—way outside.
private void saveButton_Click(object sender, EventArgs args)
{
try
{
SaveFile(myFile); // The using statement will appear somewhere in here.
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
}
Both are valid syntax. It really comes down to what you want to do: if you want to catch errors relating to creating/disposing the object, use the second. If not, use the first.
There is one important thing which I'll call out here: The first one will not catch any exception arising out of calling the MyClass constructor.
From C# 8.0 on, you can simplify using statements under some conditions to get rid of the nested block, and then it just applies to the enclosing block.
So your two examples can be reduced to:
using var myObject = new MyClass();
try
{
// something here...
}
catch(Exception ex)
{
// Handle exception
}
And:
try
{
using var myObject = new MyClass();
// something here...
}
catch(Exception ex)
{
// Handle exception
}
Both of which are pretty clear; and then that reduces the choice between the two to a matter of what you want the scope of the object to be, where you want to handle instantiation errors, and when you want to dispose of it.
If the object you are initializing in the Using() block might throw any exception then you should go for the second syntax otherwise both the equally valid.
In my scenario, I had to open a file and I was passing filePath in the constructor of the object which I was initializing in the Using() block and it might throw exception if the filePath is wrong/empty. So in this case, second syntax makes sense.
My sample code :-
try
{
using (var obj= new MyClass("fileName.extension"))
{
}
}
catch(Exception ex)
{
//Take actions according to the exception.
}
From C# 8.0, I prefer to use the second one same like this
public class Person : IDisposable
{
public Person()
{
int a = 0;
int b = Id / a;
}
public int Id { get; set; }
public void Dispose()
{
}
}
and then
static void Main(string[] args)
{
try
{
using var person = new Person();
}
catch (Exception ex) when
(ex.TargetSite.DeclaringType.Name == nameof(Person) &&
ex.TargetSite.MemberType == System.Reflection.MemberTypes.Constructor)
{
Debug.Write("Error Constructor Person");
}
catch (Exception ex) when
(ex.TargetSite.DeclaringType.Name == nameof(Person) &&
ex.TargetSite.MemberType != System.Reflection.MemberTypes.Constructor)
{
Debug.Write("Error Person");
}
catch (Exception ex)
{
Debug.Write(ex.Message);
}
finally
{
Debug.Write("finally");
}
}
Which one is better in structure?
class Program
{
static void Main(string[] args)
{
try
{
using (Foo f = new Foo())
{
//some commands that potentially produce exceptions.
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
or...
class Program
{
static void Main(string[] args)
{
using (Foo f = new Foo())
{
try
{
//some commands that potentially produce exceptions.
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Either is fine, depending on what you are going to do in the catch. If you need to use f in your catch then it needs to be within the using statement. However in your example there is no difference.
EDIT:
As pointed out elsewhere it also depends on whether you are trying to catch just exceptions generated in the block following the using or including the object creation in the using statement. If it is in the block following the using then it is as I described. If you want to catch exceptions generated by Foo f = new Foo() then you need to use the first method.
I don't think it matters much, performance-wise. There is a slight difference though; in the second example, f is still available inside the exception handler, while in the first, it has gone out of scope. Conversely, in the first example, exceptions in the Foo constructor as well as its Dispose method will be caught, while in the second, they won't.
Either may or may not be what you want.
Check this post to understand better : http://www.ruchitsurati.net/index.php/2010/07/28/understanding-%E2%80%98using%E2%80%99-block-in-c/
Also read answers of this question : Catching exceptions thrown in the constructor of the target object of a Using block
the first one is bettwer one
class Program
{
static void Main(string[] args)
{
try
{
using (Foo f = new Foo())
{
//some commands that potentially produce exceptions.
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
because if you see the IL code of this try and catch block not wrap the inialization of the object.
The first is better, because it will catch any exceptions thrown during the dispose process. Of course, you shouldn't throw any exceptions when disposing, but stuff happens.
First one is the better one .if any exception comes it will catch.
try
{
using (Foo f = new Foo())
{
//some commands that potentially produce exceptions.
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
The concept of using is it will dispose the object created in the using.i.e it automatically calls the IDispose method.Based on the requirement use the using.
Using is just
Foo f = null;
try
{
f = new Foo();
}
finally
{
if (f is IDisposable)
f.Dispose();
}
Seeing that you can achive catching exceptions like this:
Foo f = null;
try
{
f = new Foo();
}
catch (Exception ex)
{
// handle exception
}
finally
{
if (f is IDisposable)
f.Dispose();
}