Reputation: 7210
The msdn documentation of the System.IDisposable interface states that
The primary use of this interface is to release unmanaged resources.
I'm wondering what are alternative uses.
For example we also needed the IDisposable interface for other allocated resources, such as event subscription and so.
We used the interface as a marker to allow a class instance to know when it's no more used from clients. Client and infrastructural code explicitly call IDisposable.Dispose() whenever they no more need a logical instance of a class implementing the code. There's no relation with unmanaged resources wrapped from the interface.
When we choosed the IDisposable interface for such a behaviour we considered it as an alternative (undocumented) use of the interface.
Which are the alternative use of IDisposable you have found? Are they legittimate? Is the MSDN documentation wrong?
Upvotes: 1
Views: 871
Reputation: 4830
Have a look at the following question Need an alternative to my IDisposable Hack
There i give a nice example of what i used IDisposable for. :)
Granted, it is not the ideal solution, however, it helped me a lot.
Upvotes: 0
Reputation: 81277
For "resources", substitute "responsibilities". When an object is said to hold an unmanaged resource, what that really means is that there is some task that needs to get done sometime, and the object is the only thing with the information and impetus necessary to do it. The purpose of "Dispose" isn't to get rid of any tangible entity, but rather to allow an object to "put its affairs in order". Someone is putting his affairs in order before his death isn't doing anything to himself, but rather he is ensuring that the things he has to do to persons and things outside himself get done. Likewise with IDisposable.Dispose.
Upvotes: 1
Reputation: 76590
I think your reading of the documentation is wrong. Saying that any usage of IDisposable
that is not related to unmanaged resources is undocumented is a bit like saying that any usage of System.Int32
that is not counting things is undocumented. It is an interface and has no implementation, there is no functionality there to even begin distinguishing between what's documented and what's undocumented.
The purpose of IDisposable
is simply to provide the developer with a mechanism to deterministically control the lifetime of their objects. It just so happens that this mainly a requirement for dealing with unmanaged resources.
One of the more fancy uses of IDisposable
is the using
block syntactic sugar. As others have mentioned, using
blocks give an operation scope and I think those are quite elegant.
StackOverflow uses mini profiler that uses using
blocks to identify nested regions of execution:
using (profiler.Step("Doing complex stuff"))
{
using (profiler.Step("Step A"))
{ // something more interesting here
Thread.Sleep(100);
}
using (profiler.Step("Step B"))
{ // and here
Thread.Sleep(250);
}
}
The alternative to not using using
is pretty horrible and I don't even want to mock it up here.
There have been different variations of disposable action pattern making rounds in .NET Domain Driven Design circles. Ayende has one, so does Udi Dahan in his Domain Events implementation, Jimmmy Bogard has a slightly different take on this, still in the context of Domain Events. The crux of the pattern is that you want to perform certain actions in some context, then have the context revert back to what it was before after you are done.
Ayende provides a simple example:
class UsuallyReadOnly {
//.. implementation
public IDisposable AllowModification
{
get
{
_allowModification = true;
return new DisposableAction(()=>{ _allowModification = false; } );
}
}
}
And UsuallyReadOnly
's usage:
UsuallyReadOnly foo = new UsuallyReadOnly();
using(foo.AllowModification)
{
foo.Name = "Bar";
}
Upvotes: 3
Reputation: 31548
One of the more popular uses of the IDisposable
interface is transaction scopes. You can use it to wrap some SQL logic in a transaction, and explicitly call Complete()
to end the transaction:
using (var scope = new TransactionScope())
{
using (var connection = new SqlConnection(connectString))
{
// perform sql logic
...
scope.Complete();
}
}
You could also use a similar pattern for just about anything that requires a temporary function, such as creating and deleting a temporary file:
public class TempFileProvider : IDisposable
{
public Filename { get; private set; }
public TempFileProvider()
{
Filename = Path.GetTempFileName();
}
public void Dispose()
{
File.Delete(Filename);
}
}
So you could use it like:
using (var tempFileProvider = new TempFileProvider())
{
DoSomethingWithFile(tempFileProvider.Filename);
} // deletes temp file
Upvotes: 0
Reputation: 33272
IDisposable
is often used in conjunction with using to activate and deactivate something in a definite scope even if it is not an unmanaged resource. The use you describes sound as a reference counting and for sure is not recommended.
Upvotes: 2
Reputation: 25828
Remember there is also the using pattern which acts a bit like RAII.
using ( DisposableObject obj = new DisposableObject( ) )
{
.....
}
So Dispose
gets called when the using block is exited.
Upvotes: 0