Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are nested Using statements useful?

Tags:

c#

vb.net

using

The consensus on best practice for resource-intensive operations, such as opening database connections, seems to be to use Using blocks, because the Using block "guarantees disposal of the resource... even in the case of an unhandled exception.".

Here is how most examples I've found are written:

Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
    Using connection As New SqlConnection(connectionString)
        Dim command As New SqlCommand(sql, connection)
        command.Connection.Open()
        command.ExecuteNonQuery()
    End Using
End Sub

But nested Using blocks are allowed, and I occasionally (but rarely) see the above written as:

Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
    Using connection As New SqlConnection(connectionString)
        Using command As New SqlCommand(sql, connection)
            command.Connection.Open()
            command.ExecuteNonQuery()
        End Using
    End Using
End Sub

My question: Is there any benefit to multiple nested Using blocks? Or does a single Using block already guarantee that all of the resources it contains will be disposed?

(Note: my code is in VB.NET, but the same question applies to C#.)

like image 773
Doug Avatar asked Nov 30 '22 00:11

Doug


2 Answers

the using block "guarantees disposal of the resource... even in the case of an unhandled exception."

Take that "guarantee" with a grain of salt. Many things can prevent the disposal of the resource. What if the using block contains an infinite loop? Or the block throws an exception, a hostile exception filter higher on the stack goes into an infinite loop and never returns control to the finally block associated with the using statement? Or the block calls Environment.FailFast? There are many, many things that can prevent the disposal from ever running. Never write a program that relies on disposal for its correctness. Disposal is there for politeness, to return scarce resources to the pool for others to use them.

Moreover, let me make sure this point is clear: truly unhandled exceptions are implementation-defined behavior in C#. The using block's finally clause is there to deal with the situation where an exception is thrown inside the using block and then handled somewhere else, not to deal with the situation where an exception is thrown inside the block and never handled. If that happens then it is entirely up to the implementation to determine what happens; the C# language makes a total of zero promises about the behavior of a program that throws an exception that is never handled. The resources might be disposed. They might not. You're in a building that is about to be unexpectedly demolished; do you really want to spend time washing the dishes and putting them away neatly?

Is there any benefit to multiple nested Using blocks?

Yes.

Does a single Using block already guarantee that all of the resources it contains will be disposed?

No. Only the resources that are actually mentioned by a using statement are cleaned up. That's why you nest them.

There are a few cases where technically you don't have to because the inner one takes responsibility for releasing the same resource as the outer one. But it doesn't hurt anything to nest using blocks and it makes it very clear to the reader what is going on. The best practice here is to have one using statement for every resource that you want cleaned up.

like image 174
Eric Lippert Avatar answered Dec 11 '22 09:12

Eric Lippert


Nested using blocks are definitely useful: a single block will call Dispose only on its own variable, not on other variables that may be opened inside the same block. That is why each variable that you want to clean up at a defined point in your program (which should be every variable of type implementing IDisposable) needs its own using block.

like image 43
Sergey Kalinichenko Avatar answered Dec 11 '22 07:12

Sergey Kalinichenko