user2074102
user2074102

Reputation:

Is it necessary to call "Close" when within 'using' statement upon early process termination?

If I initialize a class with the Using statement, is it necessary to call it's Close method upon early termination?

Using xmlstream As New MemoryStream()
    Try
        'Do runtime operation

    Catch ex As Exception
        Console.WriteLine("Could not fill dataset.  REASON: " & ex.Message)
        xmlstream.Close()  '<-  NECESSARY????
        Environment.Exit(-1) '<- Early termination!
    End Try
    'DO STUFF
End Using

Upvotes: 1

Views: 153

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112482

The decompiler shows that the Dispose method called at the end of the Using-statement is implemented like this:

Public Sub Dispose() Implements IDisposable.Dispose
    Me.Close()
End Sub

It is implemented by the base class System.IO.Stream.

However, since you are calling Environment.Exit(-1) the code is aborted and the Dispose method is NOT called! You can test it with this class:

Class Disp
    Implements IDisposable
    Public Sub Dispose() Implements IDisposable.Dispose
        MsgBox("Disposing")
    End Sub
End Class

and this code:

Private Sub btnTest_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnTest.Click
    Dim x = 100, y = 0, z = 0
    Using d = New Disp()
        Try
            z = x \ y
        Catch ex As Exception
            Environment.Exit(-1)
        End Try
    End Using
End Sub

It should display "Disposing" in a message box, but doesn't! If you comment out Environment.Exit(-1) the message is displayed.

The Using statement is implemented as a Try Finally statement, so your code is equivalent to two nested Try ... End Try blocks. Microsoft's documentation for the Environment.Exit Method says: "... If Exit is called from a try or finally block, the code in any catch block does not execute. ...". But the documentation is unclear on whether the finally block is executed or not. The documentation for Try...Catch...Finally Statement, however, says:

Control does not pass from a Try or Catch block to the corresponding Finally block in the following cases:

•An End Statement is encountered in the Try or Catch block.

•A StackOverflowException is thrown in the Try or Catch block.

And the documentation for the End Statement says: "The End statement calls the Exit method of the Environment class in the System namespace. ...".

Finally, putting these informations together, we can say:
   Yes you must call xmlstream.Close() before calling Environment.Exit(-1)!

See also: Calling Environment.Exit() Within a Using Block

Upvotes: 0

Matt Wilko
Matt Wilko

Reputation: 27342

Not it is not necessary. According to the IDisposable.Dispose Method documentation

"The using statement automatically closes the stream and calls Dispose on the object when the code that is using it has completed"

Having said that it is not a good idea to have Environment.Exit within a Using block as this does not call Close, or indeed Dispose. Instead you should refactor this as a function that returns True or False and act on that return value to decide whether to Exit or not

Upvotes: 3

As a sugestion, you can rewrite in this way. About, what you asked, the program will leave the closure of the method to the O.S.

Try

          Using xmlstream As New MemoryStream()
          'Do runtime operation


         End Using

Catch ex As Exception
                        Console.WriteLine("Could not fill dataset.  REASON: " & ex.Message)         
                        Environment.Exit(-1)
                    End Try
                    'DO STUFF

Upvotes: 1

Related Questions