Amazon.com Widgets

On aliasing the Dispose name...

Michael argues that the guideline we have around using a customized name for the Dispose method is a bad idea because it adds developer confusion.   This is a reasonable argument, and one that heavy hitters such as Jeffrey Richter buy into as well, so it is worth some careful thought.

 

I think the easiest way to understand this issue is via an example, let’s take a look at the System.IO.FileStream class… currently it is defined as:

 

public class FileStream: Stream, IDisposable {

    //all the normal methods

   void IDisposable.Dispose () { //explicitly implemented

       //close the file handle, etc

   }

  public void Close () {

     Dispose();

  }

}

 

Notice that the Dispose method is not public… it is explicitly implemented on the class.  This means that the Dispose method can only be called directly when an instance of the FileStream class is cast to IDisposable.  We also provide Close() method that is publicly accessible off the FileStream class.

      FileStream s = new FileStream (…);

      s.Close();// works great

      s.Dispose(); //compile error

      ((IDisposable) s).Dispose(); //works great

 

We use this combination in order to:

1.       Meet the time honored expectation that file related things are “Closed” not “Disposed”, etc.  We did not want to force every developer to learn the Dispose is just “our name for Close”…

2.       We wanted to enable FileStream to plug into generic mechanisms for ensure deterministic finalization such as C#’s using statement. 

3.       We wanted only one way to Close\Dispose a file in explicitly in code.  

 

The Jeff and Michael camp would rather see us have only the Dispose method (if my understanding is right).  While that meets goals 2 and 3 outlined above, I believe the fact that it fails 1 is a significant enough problem to warrant the additional implementation complexity of our current story.  I say implementation complexity because I don’t believe that many users actually find any additional complexity with this design.  They just use Close() and\or C#’s using support and have no problems.

 

That said, I have sympathy for the argument and, like most features explicit implementation can be abused.  As such we are working on a guideline right now to help clear that up.  Suggestions always welcome!

 

Published 06 July 03 10:01 by BradA

Comments

# JosephCooney said on July 6, 2003 11:52 PM:
re: Close vs. Dispose...what about the SqlConnection class? It implements Close() and Dispose(). From looking at the dis-assembly it looks like Dispose() calls Close() but not the other way around (but that could just be me). I understand this may have been done for connection pooling reasons, but is still makes things somewhat confusing.
# Michael Bouck said on July 7, 2003 2:03 AM:
Didn't know I was in the Jeff Richter camp! :-) I'm OK with this argument except for the fact that goal 1 is relying completely on the developer to "do the right thing" (i.e. implementing Dispose() explicitly and privately). I don't know about you, but I have seen best practices thrown out the window too many times to count (that's why smart pointers were so cool, right? It automatically saved the guy who didn't remember to AddRef()/Release() his interfaces (in most cases)). I've already seen violations of this rule in third party code and boy is it ugly when I see Dispose(), Close(), Release(), Free(), etc. all defined as public! Mostly though, and I might be being a bit pedantic, it's the "purity thing" (goal 3) that appeals to me. To be able to say, categorically, that DF is accomplished, always, in one way makes life easier on everyone. Sure, the VB guy is going to be a bit confused at first but I would argue he's going to be much more confused getting used to OOP in the first place. It's more orthogonal to see a random class in the object viewer which implements IDisposable and know that there is exactally one way to get rid of it. Having said that, if the majority still thinks this is the right way to go, I'd like to propose that the compiler at least emit a warning if Dispose() is aliased by a public method and is not explicitly implemeneted privately. FxCop isn't sufficient in my opinion, because the guy that is abusing goal 1 probably isn't running FxCop either...
# Matthew Adams said on July 7, 2003 3:33 AM:
By an extraordinary coincidence, I was having this converstaion on Friday. Personally, I think that Dispose() is a big problem in the developer community at large. Whiilst it does provide a form of deterministic finalization, people associate the term 'finalize' with 'garbage collect', which Dispose() most certainly does not. Implementing Dispose() as an under the covers method to support the 'using' idiom is fine, but, otherwise, you should really provide an explicitly documented life-cycle management policy for your object, and a separate idiom is best for that (and hence *at least* a separate method). Personally, I prefer an Acquire/Release approach from an entirely separate manager for the limited resource, and Ian suggested a duration-of-work approach, rather like DataAdapter.Fill(). Whichever way you cut it, Dispose() is essential, when it is absolutely essential, but it is over-used and badly understood at the moment. And that makes it a dangerous tool.
# Mickey Williams said on July 8, 2003 1:14 AM:
Re: The earlier comment about Close vs. Dispose in SqlConnection... In SqlConnection, Close and Dispose are not the same thing. As expected, Dispose completely releases resources, and the instance can't be used for anything ever again, try it and you'll get an ObjectDisposed exception. On the other hand, SqlConnection.Close is similar, but enables you to reuse the same instance later. Dispose depends on Close to cleanup.
# Jeffrey Richter said on July 8, 2003 11:21 PM:
Actually, I'm not opposed to FileStream offerring Close. What I am opposed to is "hiding" Dispose and forcing the FileStream variable to be cast to IDisposable in order to call Dispose. I'd be OK if both Close and Dispose were _equally_ callable.
# Frank Hileman said on July 10, 2003 9:04 PM:
I agree mostly with Jeffrey. Hiding Dispose just introduces unnecessary inconsistencies. But if people have to learn to use the .net framework, they will have to learn about Dispose, and as soon as they have learned, redundant functions such as Close just add confusion.
# K. Scott Allen's Blog said on November 7, 2004 6:51 PM:
# K. Scott Allen's Blog said on November 7, 2004 6:44 PM:
# Kevin Wan said on January 16, 2007 5:06 AM:

当我们开发C#代码的时候,经常碰到一个问题,有些class提供Close(),有些class提供Dispose(),而且有些class里面还提供了Dispose(bool),那么Dispose和Close到底有什么区别?

# 夏亚兵 said on May 16, 2007 11:16 PM:

当我们开发C#代码的时候,经常碰到一个问题,有些class提供Close(),有些class提供Dispose(),那么Dispose和Close到底有什么区别?首先,Dispose和Close基本上...

# 勤勤同学 said on June 22, 2007 3:27 AM:

当我们开发C#代码的时候,经常碰到一个问题,有些class提供Close(),有些class提供Dispose(),那么Dispose和Close到底有什么区别?

# 菩提树下的杨过 said on March 9, 2008 5:09 AM:

原文地址:http://www.cnblogs.com/kevinwan/archive/2007/01/16/621869.html 当我们开发C#代码的时候,经常碰到一个问题,有些clas...

# ljsql said on April 2, 2008 9:48 PM:

正确实现IDisposable Dispose和Close的区别

# ??????????????? » Blog Archive » C#???Dispose???Close????????? | ???????????? said on May 24, 2008 11:25 PM:

PingBack from http://www.zuu.cn/1958.html

# C#???Dispose???Close????????? | ??????????????? said on March 15, 2009 9:46 AM:

PingBack from http://docman.cn/development/c-sharp/k-343822-14540/

# 菩提树下的杨过 said on June 13, 2009 8:34 AM:

原文地址:http://www.cnblogs.com/kevinwan/archive/2007/01/16/621869.html 当我们开发C#代码的时候,经常碰到一个问题,有些clas...

New Comments to this post are disabled

Search

This Blog

Syndication

Page view tracker