Given a method
public static bool Connection.TryCreate(out Connection connection) {}
And a piece of calling code:
Connection connection;
if (!Connection.TryCreate(out connection))
// handle failure gracefully.
/*
* work with connection
*
* …
*
*/
connection.Dispose();
I'm using the same pattern as bool.TryParse and friends, i.e. TryCreate returns whether the operation was successful.
I realize the using() variable needs to be read-only within its block, but is there a way to turn the above into a using() {} block (TryCreate only sets it once), like so:
using (Connection connection)
{
if (!Connection.TryCreate(out connection))
// this would leave the using() block prematurely
/*
* work with sconnection
*
* …
*
*/
}
(This doesn't compile:
error CS1657: Cannot pass 'connection' as a ref or out argument because it is a 'using variable'
)
No, that is not possible.
The using (x) {...} construct makes a copy of x when it enters the block, so you can do this:
var x = new FileStream(...);
using (x)
{
x = null;
}
The stream will still be disposed when the using block ends.
The corollary is that this won't work either:
Stream x = null;
using (x)
{
x = new FileStream(...);
}
here the stream you construct inside the using block will not be disposed.
What you can do, however, is this:
Connection connection;
if (Connection.TryCreate(out connection))
using (connection)
{
}
In C# 7.0 and onwards you can combine this with "out variables" to form:
if (Connection.TryCreate(out var connection))
using (connection)
{
}
Looks like a bad use of the Try* pattern (some would argue this is an anti-pattern).
Instead of a TryCreate, just have a Create method that throws an exception if not successful and that returns the created connection.
Then you could do the usual:
using(Connection connection = Connection.Create())
{
}
Alternatively, if you want to avoid an exception being thrown and the required try{}catch{}, have the Create method return null when a connection could not be created and test for that.
You can do it like this:
Connection connection;
if (Connection.TryCreate(out connection))
{
using (connection)
{
…
}
}
But it might be better if you just returned null on failure:
using (Connection connection = Connection.Create())
{
if (connection != null)
{
…
}
}
The finally block that is created by the using checks whether connection is null and doesn't do anything if it is.
Also, if you're not declaring the variable in the using, then it doesn't have to be read-only.
No. If you are concerned about exceptions in the gap between a method call and the using, you could use try/finally:
Connection conn = null;
try {
if(!conn.TryCreate(out conn)) return;
...
} finally {
if(conn != null) conn.Dispose();
}
A step sideways ?
public class ConnectTo : IDisposable
{
public Connection CurrentConnection {get; private set;}
public ConnectTo()
{
CurrentConnection = null;
// Connect up to whatever.
}
#region IDisposable
// Blah blah
#endregion
}
then
using( ConnectedTo conn = new ConnectTo())
{
if (conn.CurrentConnection != null)
{
//Do Stuff
}
}
Related
This question already has answers here:
What is the C# Using block and why should I use it? [duplicate]
(9 answers)
Closed 5 years ago.
I wonder that what is the difference between ;
using (var con = new OracleConnection(oradb))
{
con.Open();
// Do sth.
con.Dispose();
con.Close();
}
from this;
oradb = ConString;
OracleConnection con = new OracleConnection(oradb))
con.Open();
// Do Sth.
con.Dispose();
con.Close();
Both of them works for me, However didn't understand the basic behind of this.
Which one should i use ?
If we look at the decompiled code:
using System;
public class C {
public void M() {
using(var conn = new Connection()){
}
}
}
is turned into:
public class C
{
public void M()
{
Connection connection = new Connection();
try
{
}
finally
{
if (connection != null)
{
((IDisposable)connection).Dispose();
}
}
}
}
Unlike the code without a using block, the connection will be disposed even if the exception is thrown.
A bit more reading about the using could be found here (C# Reference doc)
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.
Using ensures that the connection is always disposed. If you dispose it manually it can happen that part of the code is never executed at all.
With using, disposing of connection is handled automaticaly :
using (var con = new OracleConnection(oradb))
{
con.Open();
// Do sth.
con.Close();
} // ok
using with dispose your connection object automatically. you dont have to do it manually.
using(var con = new OracleConnection(oradb))
{
con.Open();
}
is equal to (some what similar , you can use ILDSAM on your code and check)
OracleConnectioncon = null;
try
{
con = new OracleConnection(oradb);
con.Open();
}
finally
{
con.Disponse();
}
you can clear you concept by reading : Dispose Pattern
I frequently use the following code (or alike) to dispose of objects:
SqlCommand vCmd = null;
try
{
// CODE
}
catch(Exception ex) { /* EXCEPTION HANDLE */ }
finally
{
if (vCmd != null)
{
vCmd.Dispose();
vCmd = null;
}
}
Is this the best way to release objects and dispose of objects?
I'm using the VS analytics and give me a warning about redundancies. But I always do it this way...
The best way in terms of readability is using the using statement:
using(SqlCommand vCmd = new SqlCommand("...", connection)
{
try
{
// CODE
}
catch(Exception ex)
{
// EXCEPTION HANDLE
}
}
It disposes objects even in case of error, so similar to a finally. You should use it always when an object implements IDisposable which indicates that it uses unmanaged resources.
Further reading:
Cleaning Up Unmanaged Resources
there is no need to set objects to null.
Here is an example from MSDN:
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
Note the use of "using" for the connection.
Back in the Olden Days of COM/ActiveX, you needed to set your objects to "Nothing".
In managed code, this is no longer necessary.
You should neither call "Dispose()", nor set your sqlCommand to "null".
Just stop using it - and trust the .Net garbage collector to do the rest.
If i have some code like this and an error occurs in the second using statement, will the dispose method on 1st using not be called?
using (System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(cnstr))
{
cn.Open();
using (SqlTransaction tran = cn.BeginTransaction(IsolationLevel.Serializable))
{
--EDIT--
Also is it better to write Try / Finally block or using statement. Internally compilter will generate Try / Finally for using statement but as per coding standards which one is better?
No, both will be called. Just because an exception is called in the inner statement, doesn't mean that the first is ignored.
a using statement is just another syntax for:
var iDisposableItem = new Item();
try
{
......
}
finally
{
iDisposableItem.Dispose();
}
so in your example:
var iDisposableItem = new Item();
try
{
var iDisposableItem2 = new Item();
try
{
throws exception
}
finally
{
iDisposableItem2 .Dispose();
}
}
finally
{
iDisposableItem.Dispose();
}
Now what should be noted and what you have to be careful about is that whatever caused the first exception could cause problems with the outer using statement when it calls Dispose(). The exception could throw the (really either) object into a faulted state and calling Dispose might result in another different exception which "masks" the first one. This is a gotcha in WFC when using using statements: http://msdn.microsoft.com/en-us/library/aa355056.aspx
A using statement is nothing but a try/finally in disguise, unless the process is forcibly terminated, your objects will be disposed of correctly.
In other words, this:
using (Type1 x = new Type1())
{
// a
using (Type2 y = new Type2())
{
// b
}
// c
}
Is actually similar to this (this is simplified):
Type1 x = new Type1();
try
{
// a
Type2 y = new Type2();
try
{
// b
}
finally
{
y.Dispose();
}
// c
}
finally
{
x.Dispose();
}
It will dispose both, and you can shorten it like:
using (SqlConnection cn = new SqlConnection(cnstr), SqlTransaction tran = cn.BeginTransaction(IsolationLevel.Serializable))
{
cn.Open();
}
Suppose that I have the following code:
private void UpdateDB(QuoteDataSet dataSet, Strint tableName)
{
using(SQLiteConnection conn = new SQLiteConnection(_connectionString))
{
conn.Open();
using (SQLiteTransaction transaction = conn.BeginTransaction())
{
using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM " + tableName, conn))
{
using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter())
{
sqliteAdapter.Update(dataSet, tableName);
}
}
transaction.Commit();
}
}
}
The C# documentation states that with a using statement the object within the scope will be disposed and I've seen several places where it's suggested that we don't need to use try/finally clause.
I usually surround my connections with a try/finally, and I always close the connection in the finally clause. Given the above code, is it reasonable to assume that the connection will be closed if there is an exception?
You are correct; the using statement compiles to a try / finally block.
The compiler transforms using(resource) statement; into the following code:
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
(The cast to IDisposable is in case ResourceType implements IDisposable explicitly.
Yes, you either need to use a try/finally or a using statement. You don't need both.
A using statement is almost the same as a try/finally except that in C# 3 you can't reassign to the variable inside the using block.
using (IDisposable d = foo())
{
d = null; // Error: Cannot assign to 'd' because it is a 'using variable'
}
Previously you could reassign but the original object would still be disposed, not the newly assigned object and you would also get this compile warning:
Possibly incorrect assignment to local 'd' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
Yes, the using statement is pretty much just shorthand for a try ... finally block.
For example, this code...
using (MyDisposableType foo = new MyDisposableType())
{
foo.DoSomething();
}
...would equate to the following...
{
MyDisposableType foo = new MyDisposableType();
try
{
foo.DoSomething();
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}
You can assume that the connection will be closed if you get an exception.
Using() ensures that the item instantiated within the parameters will be disposed of regardless of that happens within the associated code block. This includes closing the database connection assuming that SQLiteConnection handles its disposal correctly.
Edit: Two options shown below.
If you're just using the functionality that an IDisposable provides, the aptly named using clause works fine. If you're wrapping an IDisposable in an object, the containing object itself needs to be IDisposable and you need to implement the appropriate pattern (either a sealed IDisposable class, or the messier but standard virtual pattern).
But sometimes a helper factory method is good for cleanliness. If you return an IDisposable directly after construction, you're fine, but if you first construct it and then modify it or otherwise execute code that can throw an exception before returning, you need to safely call .Dispose() - but only if there was an error.
For example, unsafe code could look like this...
DbCommand CreateCommandUnsafely(string commandText)
{
var newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //what if this throws?
return newCommand;
}
Solutions Two safe variants follows...
DbCommand CreateCommandSafelyA(string commandText)
{
DbCommand newCommand = null;
bool success = false;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
success=true;
return newCommand;
} finally{
if (!success && newCommand != null )
newCommand.Dispose(); //...we'll clean up here.
}
}
DbCommand CreateCommandSafelyB(string commandText)
{
DbCommand newCommand = null;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
return newCommand;
} catch {
if (newCommand != null)
newCommand.Dispose(); //...we'll clean up here.
throw;
}
}
Safe variant A is just one line longer, but seems to be the idiomatic approach. There don't seem to be any really concise solutions, although some posters below give some lambda-using options that extract the encapsulate this logic.
The code bloat with any of the above safe methods remains, and is particularly aggravating with code that originally looked like...
return new MyDisposableThing {
OptionA = "X",
OptionB = B.Blabla,
Values = src.Values.Where(priority => priority > 1.0),
};
The above code gets written safely is quite a bit longer and less readable because you can no longer safely use the shortened setter syntax.
No - I think there isn't a better way.
However, you could write a helper class:
public static class DisposeHelper
{
public static TDisposable DisposeOnError<TDisposable>(TDisposable dispoable, Action<TDisposable> action)
where TDisposable : IDisposable
{
try
{
action(dispoable);
}
catch(Exception)
{
disposable.Dispose();
throw;
}
return disposable;
}
}
So you could write:
return DisposeHelper.DisposeOnError(connection.CreateCommand(), cmd => cmd.CommandText = commandText);
I am not sure, however, if that is really a better way.
I believe this is the standard pattern:
DbCommand CreateCommand(string commandText)
{
DbCommand newCommand = null;
bool success = false;
try
{
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText;
success = true;
return newCommand;
}
finally
{
if (!success & newCommand != null)
newCommand.Dispose();
}
}
It does not catch and rethrow the error.
You could consider writing an Extension Method:
public static class Disposable
{
public static void SafelyDo<T>(this T disp, Action<T> action) where T : IDisposable
{
try
{
action(disp);
}
catch
{
disp.Dispose();
throw;
}
}
}
This would allow you to write code like this:
var disp = new MyDisposable();
disp.SafelyDo(d =>
{
d.Foo = "Ploeh";
d.Bar = 42;
});
return disp;
I think you are overcomplicating the issue.
If your method returns a disposable object, then you are saying "I hereby relinquish ownership of this object, for better or worse". If an error occurs while you are building it, then why should that make a difference? The calling code will still dispose of it even if you throw an exception.
For example:
DbCommand CreateCommand(string commandText) {
var newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; // what if this throws?
return newCommand;
}
void UseCommand() {
using(var cmd = CreateCommand("my query goes here")) {
// consume the command
}
}
Edit: Unfortunately, if an exception is thrown inside CreateCommand, the cmd variable is never set and the object will not be disposed correctly.