This may be answered elsewhere, but after doing a bit of searching I didn't find much on the subject outside of the normal using
context.
I am curious if all objects created in a using
block will be disposed of as well as the original object.
Here is the context:
Normally I would do something like this:
using (var conn = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(commandText, conn))
{
//Do everything I need to here
}
I know that both conn
and cmd
go out of scope at this point and are disposed of because of the lovely using
keyword.
I am curious if the same disposal rules would apply to the following statement:
using (var cmd = new (SqlCommand(commandText, new SqlConnection(ConnectionString)))
{
//Do everything I need here
}
Would the SqlConnection
object that was created inline in the using
statment be disposed of when cmd
goes out of scope and is disposed of because it's associated with the object?
Also which would be syntactically preferred? I personally think the 2nd is cleaner, but I understand readability may come to play here as well.
For your second code, Dispose
won't be called on SqlConnection
instance when flow leaves using
block unless SqlCommand.Dispose()
do that internally (and no, it doesn't).
According to specification (8.13), using (ResourceType resource = expression) statement
is transformed into:
{
ResourceType resource = expression;
try {
statement;
}
finally {
if(resource != null)
((IDisposable)resource).Dispose();
}
}
In your code, resource
is SqlCommand
, and that's the one Dispose
is called on.
No.
using
statements only apply to the resources declared directly in the statement; not to other allocations in the initializer.
You need a separate using
statement for each resource.
According to MSDN, this code:
using (var temp = obj)
{
// ...
}
Translates to (including the extra curly braces to limit the scope):
{
var temp = obj;
try
{
// ...
}
finally
{
if (temp != null)
((IDisposable)temp).Dispose();
}
}
As you can see, if you substitute obj
for new SqlCommand(commandText, new SqlConnection(ConnectionString))
then only the SqlCommand
gets properly disposed.
{
SqlCommand temp = new SqlCommand(commandText,
new SqlConnection(ConnectionString));
try
{
// ...
}
finally
{
if (temp != null)
((IDisposable)temp).Dispose();
}
}
So, the SqlConnection
won't get disposed unless the disposed SqlCommand
does that. But it doesn't, and it shouldn't: it didn't create the object, therefore it must not destroy it either.
Certainly there are already answers that explains this correctly. This is covered by the specification as mentioned by others.
But you could just try it out. Here is an example:
static class Program
{
static void Main()
{
using (new DisposeMe("outer", new DisposeMe("inner", null)))
{
Console.WriteLine("inside using");
}
Console.WriteLine("after using scope");
}
}
class DisposeMe : IDisposable
{
public readonly string name;
public DisposeMe(string name, object dummy)
{
this.name = name;
}
public void Dispose()
{
Console.WriteLine("'Dispose' was called on instance named " + name);
}
}
Output:
inside using 'Dispose' was called on instance named outer after using scope
(Of course if you nest two using
statements, as in using (var inner = new DisposeMe("inner", null))
{
using (new DisposeMe("outer", inner))
{ ... } }
, the Dispose
method is called on both objects.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With