Doug
Doug

Reputation: 2610

Are nested Using statements useful?

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#.)

Upvotes: 5

Views: 2780

Answers (5)

Gary Walker
Gary Walker

Reputation: 9134

Nested using statements are quite useful. However many programmers don't consider that the SqlCommand object needs to have resource cleanup. I.e., the resource is the connection, not the command.

ADDED

SqlCommand does not have a Close() method, so even though SqlCommand has a Dispose() method, the lack of a Close() method indicates that there is really "nothing to close / release". Disposable instances will always be Disposed eventually. Hard to find something authoritative without digging through source, but when asked in this article the MS guy was asked exactly what it disposed, he said "Actually not a lot ..." and went on to suggest a USING clause for the SqlCommand(), so I answered the question correctly, but avoided the fuzziness behind it initially.

Upvotes: 1

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73482

All other answers are correct. I'll add one more point.

If objects are of same type c# compiler provides a way(syntatic sugar) to use multiple objects in single using statement inline.

C# version

using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream())
{

}

Vb.Net version

Using ms1 = New MemoryStream(), ms2 = New MemoryStream()

End Using

This will dispose both the MemoryStreams

Upvotes: 1

Eric Lippert
Eric Lippert

Reputation: 660159

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.

Upvotes: 10

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726669

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.

Upvotes: 8

SLaks
SLaks

Reputation: 887509

The Using statement will dispose the variables declared within the Using line.
It has no effect on variables declared elsewhere in the block.

You should always use a Using statement for every disposable variable.

Upvotes: 3

Related Questions