Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using 'Using' for things other than resource disposal [duplicate]

We all know that the using statement is really good for resources you want to cleanup in a timely manner, such as an open file or database connection.

I was wondering if it would be considered a good thing to use the statement in cases where resources cleanup isn't the goal of the Dispose() method, but rather resetting to a previous state.

For example, a class that allows a using statement to wrap a procedure that takes a noticeable amount of time and changes the Cursor to a waiting state.

class CursorHelper : IDisposable
{
   readonly Cursor _previousState;
   public CursorHelper(Cursor newState)
   {
      _previousState = Cursor.Current;
      Cursor.Current = newState;
   }

   public void Dispose()
   {
      Cursor.Current = _previousState;
   }
}

Then the class can be used as such, without worrying about reverting the Cursor when your are done.

public void TimeIntensiveMethod()
{
   using (CursorHelper ch = new CursorHelper(Cursors.WaitCursor))
   {
      // something that takes a long time to complete
   }
}

Is this an appropriate use of the using statement?

like image 918
Cemafor Avatar asked May 29 '13 13:05

Cemafor


People also ask

What is the use of Dispose method?

The Dispose() method The Dispose method performs all object cleanup, so the garbage collector no longer needs to call the objects' Object. Finalize override. Therefore, the call to the SuppressFinalize method prevents the garbage collector from running the finalizer. If the type has no finalizer, the call to GC.

When should you use IDisposable?

If you access unmanaged resources (e.g. files, database connections etc.) in a class, you should implement IDisposable and overwrite the Dispose method to allow you to control when the memory is freed.

What is using () in C#?

The using statement causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and can't be modified or reassigned. A variable declared with a using declaration is read-only.

Is IDisposable called automatically?

By default, the garbage collector automatically calls an object's finalizer before reclaiming its memory. However, if the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer.


2 Answers

There are certainly precedents for (ab)using the using statement in this way, for example FormExtensions.BeginForm in the ASP.NET MVC framework. This renders a <form> closing tag when it's disposed, and it's main purpose is to enable a more terse syntax in MVC views. The Dispose method attempts to render the closing tag even if an exception is thrown, which is slightly odd: if an exception is thrown while rendering a form, you probably don't want to attempt to render the end tag.

Another example is the (now deprecated) NDC.Push method in the log4net framework, which returns an IDisposable whose purpose is to pop the context.

Some purists would say it's an abuse, I suggest you form your own judgement on a case-by-case basis. Personally I don't see anything wrong with your example for rendering an hourglass cursor.

The discussion linked in a comment by @I4V has some interesting opinions - including arguments against this type of "abuse" from the ubiquitous Jon Skeet.

like image 59
Joe Avatar answered Sep 21 '22 12:09

Joe


In reality using is simply syntactical sugar for try/finally, so why don't you just do plain old try/finally like below...

try
{
    // do some work
}
finally
{
    // reset to some previous state
}

imho implementing the Dispose method to reset to some state would be very misleading, especially if you have consumers for your code.

like image 23
Jason Avatar answered Sep 24 '22 12:09

Jason