Search code examples
c#idisposablemsdn

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?


Solution

  • 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";
    }