How to handle exceptions thrown by disposable objects?

What is the best way to use disposable objects, assuming the Constructor and Process methods can throw an exception? I usually prefer one of the following implementations.

  • Try the environment using the block

    try { using (Disposable dispObj = new Disposable()) { dispObj.Process(); } } catch (Exception ex) { // Do something } 
  • try-catch-finally block.

     Disposable dispObj2 = null; try { dispObj2 = new Disposable(); dispObj2.Process(); } catch (Exception ex) { // Do something } finally { if (dispObj2 != null) { dispObj2.Dispose(); } } 

UPDATE:

Again: "assuming the Constuctor and Process methods may throw an exception . " I really don't understand why no one cared about exceptions in their answers.

+6
source share
8 answers

using is good. It has a built-in try-finally block. If an exception occurs, the dispose method is called automatically.

This is normal

 using (Disposable dispObj = new Disposable()) { dispObj.Process(); } 
+10
source

Do it like this:

 using (Disposable dispObj = new Disposable()) { dispObj.Process(); } 

Disposable objects are always deleted when they go out of scope using , even if it is an exception.

And do not use empty catch {} , completely meaningless.

+3
source

using statement uses try - finally in the background and only works with an object that implements IDisposable. You do not need to use try catch using. Take a look at the following example (From MSDN - Using an Operator ).

 using (Font font1 = new Font("Arial", 10.0f)) { byte charset = font1.GdiCharSet; } 

The above code is the same as:

 Font font1 = new Font("Arial", 10.0f); try { byte charset = font1.GdiCharSet; } finally { if (font1 != null) ((IDisposable)font1).Dispose(); } 
+3
source
 using (Disposable dispObj = new Disposable()) { dispObj.Process(); } } 
+2
source

Classes that implement the IDisposable interface typically use resources that cannot be cleared by the .NET framework garbage collector. Calling the IDisposable.Dispose () method executes code that explicitly frees up a valuable resource in the world. A striking example of a class that implements the IDisposable interface is the SqlConnection class. The SqlConnection class uses a connection to a Microsoft SQL Server database. Because SQL Server supports a limited number of connections, it is important that you release the connection as soon as possible. Typically, you do not call the Dispose () method directly. Typically, you use the Using statement in your code, as you mentioned in your code

+1
source

If possible, you should use a usage block. This ensures that Dispose is called on your object. Doing this manually is error prone.

0
source
 using (IDisposable disp = new IDisposable()) { //some logic here } 

This code will be translated as follows:

 IDisposable disp = new IDisposable(); try { //some logic here } finally { if (disp != null) ((IDisposable)disp).Dispose(); } 

The code in the finally block is always executed, so it gives you the ability to throw exceptions, returning from using the block without any doubt that Dispose will not be called.

But you have to be careful with using initializers and objects.

 using (var fs = new FileStream(@"C:\blabla", FileMode.Open) { Position = pos }) { //some logic here } 

As you can see from here, the Position property can throw exceptions. And the problem is that the object will be created, and it will be made from a try block , so a memory leak may occur. Right way to that

 using (var fs = new FileStream(@"C:\blabla", FileMode.Open)) { fs.Position = pos; //some logic here } 
0
source

Method number 1 that you proposed is most likely the shortest way to achieve what you want.

The surrounding try ... catch should catch any exceptions thrown, including those thrown by the constructor. If an exception occurs when a one-time object is used (inside the using block), the object will also be deleted before it accepts catch .

Method # 2 performs a different execution path from method # 1. Note that according to the C # link, method # 1 compiles literally, as if the following were written:

 try { { Disposable dispObj = new Disposable(); try { dispObj.Process(); } finally { if (dispObj != null) ((IDisposable)dispObj).Dispose(); } } } catch (Exception ex) { // Do something } 

So, the areas between the two methods are different. I would prefer Method No. 1 when possible, due to coverage issues, and also because it is easier to read.

0
source

Source: https://habr.com/ru/post/921829/


All Articles