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
}
}
of the using
statement can throw an exception as reminded here.
finally
called the dispose method.
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();
}
}
finally
block is preferable to the using
statement?
finally
block that disposes an IDisposable object is what a using
statement does. Personally, I like this instead of the embedded using
block because I think it more cleanly states where everything is happening, and that it's all on the same "level". I also like this more than several embedded using
blocks... but it's all just my preference.
try
statement for it to be disposed within the finally
statement; otherwise, it will throw a compiler error: "Use of unassigned local variable 'myObject'"
Cannot assign null to implicitly-typed local variable
;) But I know what you mean and personally would prefer this to nesting a using block.
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 catch
es.
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");
}
}
Success story sharing
try
block, which allows you to pop an error message if something fails, the program now has the ability to recover and inform the user.using( DBConnection conn = DBFactory.getConnection())
which would need to be rolled back in case of an exception that occurred. Seems to me that both have their place.