In this particular example, you can in fact do this:
using (var conn = new SqlConnection(...)) {
// Do work
}
What the compiler does with that statement is essentially:
SqlConnection conn;
try {
conn = new SqlConnection(...)
} finally {
conn.Dispose();
}
Or thereabouts... the finally block is always exected, ensuring that a using block always calls Dispose.
The downside of this approach is that you can't catch the SqlException that could be thrown, so you end up doing something like this:
try {
using (var conn = new SqlConnection(...)) {
// Do work.
}
} catch (SqlException ex) {
}
But the compiled code ends up representing:
try {
SqlConnection conn;
try {
conn = new SqlConnection(...);
} finally {
conn.Dispose();
}
} catch (SqlException ex) {
}
To be honest though it probably won't make any difference performance wise, as anytime you throw an exception, its going to be a performance hit. It does ensure that Dispose is always called.