Reputation: 35721
This is a rather basic question, however I'm still struggling with it a little.
IDisposable
is implemented, when you want to enable the user of an object to free underlying resources (e.g. sockets etc.) before the object is eventually garbage collected.
When i have a class that holds a DbConnection
(implements IDisposable
), does my class need to implement IDisposable
too and chain the call down to the DbConnection or any other IDisposable objects it owns? Else the DbConnections
resources will only be freed when my class is garbage-collected, thereby drops it reference to the connection and GC will finalize the DbConnection
.
Upvotes: 15
Views: 1086
Reputation: 564333
You should do this, since it's the only way for the user of your class to make sure that the internally held resource is properly disposed.
However, the pattern used for Dispose() may be slightly different than what is commonly written, in this case, since you don't have to differentiate between unmanaged and managed resources (your encapsulated resource is always treated as a "managed" resource).
I wrote a detailed blog post on this specific topic - Encapsulating IDisposable Resources.
Upvotes: 3
Reputation: 30847
Yes, you ALWAYS implement IDisposable if you control disposable objects. ALWAYS. Your code won't break if you don't, but it defeats the purpose of having disposable objects if you don't.
The general rule for GC optimization is:
These rules may be bent or ignored if you're writing an application for yourself, but when distributing code to others you should be professional and follow the rules.
The logic here is that when you control memory outside the view of the GC the GC engine can't properly manage your memory usage. On your .NET heap, for example, you may just have a 4-byte pointer, but out in unmanaged land you could have 200 MB of memory being pointed at. The GC engine wouldn't attempt to collect these until you have several dozen, because all it sees is a few bytes; while in the real world it looks a lot like a memory leak.
Therefore, the rule is, unmanaged memory should get freed immediately when you're done using it (the IDisposable chain does this for you), while managed memory gets freed by the GC engine whenever it gets around to it.
Upvotes: 10
Reputation: 391286
There are two distinct scenarios:
In the second case, your object is responsible for the resources involved, so your object must implement IDisposable, and when disposed of, you should dispose of the object you constructed.
Your DbConnection falls under this second case, so yes, your object should implement IDisposable, and then dispose of the connection.
In the first case, you need to decide on the following three solutions:
That was a lot of text, so let me summarize:
There's also a third case, which it doesn't sound like you're having, but nonetheless.
In the case when you construct, use, and discard, an object locally, inside a single method, without passing it around or storing it in fields of the class, you use the using
statement instead, like this:
using (IDbConnection conn = ....())
{
}
Upvotes: 2
Reputation: 566
When you provide explicit control using Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose.
I think best way to implement this is use combination of Dispose and Finalize method. You can find more Here.
Upvotes: 0
Reputation: 171
Of course you can remove a lot of the (re)implementation cost of IDisposable and get something pretty close to deterministic finalization of objects on the managed heap if you use C++/CLI. This is a often (I find) overlooked aspect of a language that a lot of folks seem to consign to the "for glue code only" bin.
Upvotes: 0
Reputation: 5320
Since we never know when an object is going to be collected by GC we use IDisposable interface to have a chance to intentionally release unmanaged resources before an object is garbage collected. If an disposable object is not dispose before being collected its resources might not been released until the AppDomain is exited. It's almost an unwritten rule that every object that has a reference to an IDisposable object should be IDisposable itself and call Dispose method of its IDisposable references in its own Dispose method.
Upvotes: 0
Reputation: 1859
If I understand your question correctly, you have a class that uses a DbConnection. You want to ensure that the DbConnection is correctly disposed when you are done working with it or when your class is disposed. There are a couple of ways to achieve this.
If you are using a database connection as a local variable in a method then you can leverage the using() {} statement.
using (SqlConnection sqlConnection = new SqlConnection(connStr))
{
...do stuff with connection here
}
The using () {} statement automatically calls Dispose() on objects declared within the (). (It also requires that objects declared in the () implement IDisposable to ensure they can be disposed)
If you are instead working with a DbConnection as a private variable that is initialized during object construction or some other initialization method then you probably want to implement IDisposable yourself and then call _dbConnection.Dispose() in your Dispose() method. That way, when your object is disposed the db connection object will also dispose.
public class MyDALObj : IDisposable
{
public MyDalObj()
{
... create _dbConn object ...
}
public void Dispose()
{
_dbConn.Dispose();
}
private DbConnection _dbConn;
}
Upvotes: 3
Reputation: 6458
It is certainly best practice to do so, especially when working with heavy/unmanaged objects.
Edit: Best practice, but not mandatory.
Upvotes: 0
Reputation: 34543
Yes, your class needs to be IDisposable if it needs to dispose of any objects that it uses. An example of this is StreamReader. It implements IDisposable so it can dispose of its associated stream object.
Upvotes: 6