Norman Sasono

Beauty is the first test: there is no permanent place in the world for ugly Mathematics – G.H. Hardy
See also: Other Geeks@INDC

About Me

To Close or To Dispose or To Close then must Dispose too

Big Smile

Confused with the title? There's a lot of confusion out there on objects that implements IDisposable. And it confuses me why people must be confused. I guess because of a "myth".

Some folks say calling Dispose() is enough. Some say calling Close() is enough. Some other say one is not enough, after calling Close() you should call Disppose() too. Some other say the other way around. Some other say whether you call Close() or not, you still need to call Dispose(). Some other say the other way around. I personally think Microsoft is the one that caused this confusion. Or at least they started it.

Actually this is not about IDisposable Pattern (and Finalizer) issue. It's more an API Design issue.

Here's the story:

Classes that hold unmanaged resources must release these unmanaged resources once they're done using it. This is because unmanaged resources are not subject to be GC-ed. To ensure this happens in consistent way, a contract named IDisposable was made with Dispose() method in it that must be implemented by the classes I mentioned earlier, and code to release the unmanaged resources must be in this method. Then there is this IDisposable Pattern (see other references on this). So, developers that use instance of these classes simply have to call the Dispose() method to release unmanaged resources.

The thing is, developers easily forget to call this Dispose() method. So, C# compiler comes to rescue with the construct "using" as follow:

   using (SomeIDisposableImplementer implementer = new SomeIDisposableImplementer())
   {
        // using that implementer object
   }

C# compiler will emit code similiar to this, so that it is ensured that Dispose() will be called:

   SomeIDisposableImplementer implementer = new SomeIDisposableImplementer();
   try
   {
        // using that implementer object
   }
   finally
   {
        implementer.Dispose();              
   }

But then, the API designer think the name "Dispose" is weird for classes like FileStream for example. It is more natural that we "Close" a file rather than "Dispose" a file. So, as an alternative, a Close() method is defined, and must have the same implementation with Dispose(). So developers can call Close() instead.

Here's an illustration:

   void Dispose()
   {
            // do this
            // do that
            // do some other funky stuff
   }

A Close() method is added to the class: 

   void Close()
   {
           // do this
           // do that
           // do some other funky stuff
   }

To avoid duplicated code, a Microsoft developer might do something like:

   void Dispose()
   {
         this.close();
   }

Or the other way around.

You can see via Reflector how .NET classes that implement IDisposable's Dispose() method simply do this.Close();

So, it is very clear that one can call either Close() or Dispose(). One is enough. They are both have same implementation. This words are from Microsoft. And you can easily see in the code too.

I am confused why there are many people are confused with this. Big Smile Why there are people think that one still need to call Dispose() after one call Close() (or the other way around).

I bet they never read "CLR via C#" by Jefrrey Richter or "Framework Design Guidelines" by Brad Abrams & K. Cwalina. And they just heard the "myth" that Dispose() must be called no matter what, even after you call Close().

To me, simply disasembler the .NET classes that implement IDisposable via Reflector. And see the code. See the code you, ... !

Share this post: | | | |
Posted: Mar 16 2007, 02:30 AM by norman | with 2 comment(s)
Filed under: , ,

Comments

yulian said:

mmh..memang malah jadi bingung :( setahu saya method close dengan dispose itu berbeda, contohnya method close untuk connection dan method close untuk form. Ada kalanya kalau kita close sebuah form atau connection bukan berarti mereka di dispose,benarkah :( Implementasi IDisposable pd sebuah class utk memberitahukan pd GC bahwa object tsb akan dijadikan candidate untuk di release kalau class tsb merupakan managed code...klo class yang kita buat menggunakan unmanaged code tidak bisa langsung panggil Dispose, tapi harus overrides sub Finalize (klo di vb) di class yg bersangkutan,nnt object tsb akan masuk ke "finalization queue" stlh itu masuk ke koleksi GC then remove from "finalization queue" finally call finalize method from the class...CMIIW

# March 16, 2007 4:24 PM

norman said:

IDisposable Patterns dan Finalizers itu things yg ada di class yg implement IDisposable interface. Saya bukan bicara tentang IDisposable Pattern & Finalizers.

Saya bicara tentang class YG MEMAKAI class yg implement IDisposable. Tentang bagaimana developer hrs memanggil Dispose() jika ada class yg punya method ini. Bukan tentang bagaimana kita implement IDisposable's Dispose() dan hubungannya dgn Finalizer(). Saya menyoroti kita sbg API user, bukan sbg API creator (membuat class yg implement IDisposable).

Get it?

Close() and Dispose() itu adalah API yg bisa dipanggil oleh developer yg memakai class yg implement IDisposable tsb. "Close()" adalah alternatif method yg punya implementasi sama dgn "Dispose(). Semata-mata ada untuk mjd option saja. Jd, mau panggil Dispose() atau Close(), monggo...

Kalau isi dlm "Dispose()" adalah "this.Close();", how they can be different? :)

# March 17, 2007 10:57 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 
Are you human?:  


Enter the numbers above: