I would like to refactor my SqlDataReader
code, so it's using using
..
SqlDataReader reader = null;
reader = xdCmd.ExecuteReader();
// use reader..
Can I use solution 1) where I declare the reader
in the using and first later initialize it with a SqlDataReader
, and still get the Dispose
"features" using provides? Or do I need to do it as in solution 2), where the initialization happends right away, in the using
?
I would guess that 1) is fine, but I'm not sure.
1)
using (SqlDataReader reader = null)
{
xdCmd.CommandText = $"select * from {tableName}";
reader = xdCmd.ExecuteReader();
// use reader..
}
2)
using (SqlDataReader reader = new SqlDataReader(new SqlCommand($"select * from {tableName}"), xdCon))
{
reader = xdCmd.ExecuteReader();
// use reader..
}
The C# language does not include syntax to express the concept of object "ownership" or lifetime management unlike Rust, so it's entirely up to an API's documentation to say if an object's constructor takes ownership of its arguments or not (and thus who gets to call .Dispose()
). This is not something the C# compiler can determine for you. However .Dispose()
implementations must be idempotent anyway so there is no harm in calling .Dispose()
multiple (redundant) times.
Just follow the C# idiomatic conventions of stacked using
statements:
using( SqlConnection c = new SqlConnection( connectionString ) )
using( SqlCommand cmd = c.CreateCommand() )
{
await c.OpenAsync().ConfigureAwait(false);
cmd.CommandText = "SELECT foo, bar FROM baz";
using( SqlDataReader rdr = await cmd.ExecuteReaderAsync().ConfigureAwait(false) )
{
...
}
}