Question

Considering the semantics of IDisposable, what should the Dispose do, other than cleaning the resources of course?

I saw that many classes use Dispose method to initiate shutdown processes and some other stuff, and not just doing the "resource cleanup" work. For example, if you have a thread inside the class, which needs to be shutdown, would you expect that calling Dispose gracefully shuts down this thread?

IMHO I would implement a Stop / Shutdown method on this object, and gracefully shutdown the thread there, while in the Dispose I would check when thread is still alive to simply call Abort on it (assassination style :) ).

The same example can be with timers, and all other resources which can have the some sort of termination process before finishing you work with that object.

Two examples of conflicting designs in .NET:

  • ServiceBase for windows services has OnStop as well as Dispose to override.
  • WebApp.Start from OWIN for self-hosting gives you back an IDisposable which I guess does the service shutdown somewhere in the Dispose process.
Was it helpful?

Solution 2

Rather than thinking in terms of an IDisposable contract, it's more helpful to think of IDisposable as being part of a general Object contract which says that objects should not require any form of notice other than IDisposable.Dispose before they are abandoned (objects which don't implement IDisposable should not require any sort of notice at all). The Dispose method should do anything and everything that needs to be done before an object can be safely abandoned.

The only aspect of this which is problematical is that exceptions may occur while performing cleanup, and there's no way for Dispose to know what it should do in such case. If Dispose is called during normal (non-exceptional) program execution, it should throw an exception if cleanup fails. If it is called while unwinding the stack from from an exception, however, any exception it might throw would generally destroy all evidence of the earlier exception (thus is would often be better for it to fail silently than throw an exception). Unfortunately, there's no way via which Dispose can tell which situation applies, and thus no way for it to consistently do the right thing in case of cleanup failure.

OTHER TIPS

To be difficult, I've used dispose only do business logic. For example:

public class UsingBase : IDisposable
{
    protected Action end;
    public UsingBase(Action start, Action end) { this.end = end; if (start != null) start(); }
    public void Dispose() { if (end != null) end(); }
    public void Cancel() { end = null; }
}

class HideCursor : UsingBase { public HideCursor() : base(() => Console.CursorVisible = false, () => Console.CursorVisible = true) { } }

public static void DisplayTitle(...)
{
    ...
    using (new HideCursor())
    {
       //Display the title
    }
    ...
}

And while some may conside this an abuse of the language, I got the idea from the ASP.net API.

@using (Html.BeginForm())
{
    ...
}

To get back to your question

For example, if you have a thread inside the class, which needs to be shutdown, would you expect that calling Dispose gracefully shuts down this thread?

I'd like it to when such makes sense - because I often use objects with using, letting it take care of it's own disposal. Of course, if you clearly document your logic, and have a clear reason to differentiate 'graceful stop' from 'dispose' then that could work.

Or in other words - I don't want to be doing this for no reason:

using (var blah = new Blah())
{
...
...
...
Blah.SpecialDispose();
}//Blah.Dispose();

Because it'll cause the exact problem that using is trying to stop - people forgetting to write the right wrapper code (e.g. try finally).


Edit:

In summary. Yes, business logic can be done Dispose. Yes, Dispose can handle things 'nicely'. Those are the main questions you posed. However, that does not necessarily negate the possible use case where Dispose is used as a 'last resort' and is more abrupt in it's actions. It sounds like you are confident in your use-case, in which case go ahead. If you still want feedback I suggest posting a more specific question related to your actual use case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top