Giacomo Tesio
Giacomo Tesio

Reputation: 7210

What are IDisposable alternative uses?

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

Answers (6)

stoic
stoic

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

supercat
supercat

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

Igor Zevaka
Igor Zevaka

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.

Example 1 - timing blocks

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.

Example 2 - Disposable action

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

Igal Tabachnik
Igal Tabachnik

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

Felice Pollano
Felice Pollano

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

Nick
Nick

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

Related Questions