少了一些图片,我懒得拷了,大家还是去源地址看吧

http://www.codeproject.com/KB/cs/idispose.aspx

极力推荐!!!!

Introduction

This is yet another article on the use of the interface class IDisposable. Essentially, the code that you are going to see here is no different than the code on MSDN or these two excellent articles:

Garbage Collection in .NET by Chris Maunder:
http://www.codeproject.com/managedcpp/garbage_collection.asp

General Guidelines for C# Class Implementation by Eddie Velasquez:
http://www.codeproject.com/csharp/csharpclassimp.asp

What's different is that this article illustrates the functional aspects of:
the destructor
the Dispose method
memory allocation
garbage collection issues

In other words, there's lots of articles showing how to implement IDisposable, but very few demonstration of why to implement IDisposable.
How To Implement IDisposable

The salient features of the code below are:
Implement the Dispose method of the IDisposable interface
Only Dispose of resources once
The implementing class requires a destructor
Prevent the GC from disposing of resources if they've already been manually disposed
Track whether the GC is disposing of the object rather than the application specifically requesting that the object is disposed. This concerns how resources that the object manages are handled.

And here's a flowchart:

Note two things:
If Dispose is used on an object, it prevents the destructor from being called and manually releases managed and unmanaged resources.
If the destructor is called, it only releases unmanaged resources. Any managed resources will be de-referenced and also (possibly) collected.

There are two problem with this, which I'll come back to later:
Using Dispose does not prevent you from continuing to interact with the object!
A managed resource may be disposed of, yet still referenced somewhere in the code!

Here's an example class implementing IDisposable, which manages a Image object and has been instrumented to illustrate the workings of the class.
Collapse
public class ClassBeingTested : IDisposable
{
private bool disposed=false;
private Image img=null;

public Image Image
{
get {return img;}
}

// the constructor

public ClassBeingTested()
{
Trace.WriteLine("ClassBeingTested: Constructor");
}

// the destructor

~ClassBeingTested()
{
Trace.WriteLine("ClassBeingTested: Destructor");
// call Dispose with false. Since we're in the

// destructor call, the managed resources will be

// disposed of anyways.

Dispose(false);
}

public void Dispose()
{
Trace.WriteLine("ClassBeingTested: Dispose");
// dispose of the managed and unmanaged resources

Dispose(true);

// tell the GC that the Finalize process no longer needs

// to be run for this object.

GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposeManagedResources)
{
// process only if mananged and unmanaged resources have

// not been disposed of.

if (!this.disposed)
{
Trace.WriteLine("ClassBeingTested: Resources not disposed");
if (disposeManagedResources)
{
Trace.WriteLine("ClassBeingTested: Disposing managed resources");
// dispose managed resources

if (img != null)
{
img.Dispose();
img=null;
}
}
// dispose unmanaged resources

Trace.WriteLine("ClassBeingTested: Disposing unmanaged resouces");
disposed=true;
}
else
{
Trace.WriteLine("ClassBeingTested: Resources already disposed");
}
}

// loading an image

public void LoadImage(string file)
{
Trace.WriteLine("ClassBeingTested: LoadImage");
img=Image.FromFile(file);
}
}
Why Implement IDisposable?

Let's put this class into a simple GUI driven test fixture that looks like this:

and we'll use two simple tools to monitor what's going:
DebugView to watch the execution: http://www.sysinternals.com/ntw2k/freeware/debugview.shtml
the Task Manager's Performance view for memory utilization.

The test is very simple, involving loading a 3MB image file several times, with the option to dispose of the object manually:
Collapse
private void Create(int n)
{
for (int i=0; i<n; i++)
{
ClassBeingTested cbt=new ClassBeingTested();
cbt.LoadImage("fish.jpg");
if (ckDisposeOption.Checked)
{
cbt.Dispose();
}
}
}

The unsuspecting fish, by the way, is a Unicorn Fish, taken at Sea World, San Diego California:

Observe what happens when I create 10 fish:

Ten fish took up 140MB, (which is odd, because the fish is only a 3MB file, so you'd think no more than 30MB would be consumed, but we won't get into THAT).

Furthermore, observe that the destructors on the objects were never invoked:

If we create 25 fish, followed by another 10, notice what happens to the time it takes to haul in the fish, as a result of heavy disk swapping:

This is now taking two seconds on average to load one fish! And did the GC start collecting garbage any time soon? No! Conversely, if we dispose of the class as soon as we're done using it (which in our test case is immediately), there is no memory hogging and no performance degradation. So, to put it mildly, it is very important to consider whether or not a class needs to implement the IDispose interface, and whether or not to manually dispose of objects.
Behind The Scenes

Let's create one fish and then force the GC to collect it. The resulting trace looks like:

Observe that in this case, the destructor was called and managed resources were not manually disposed.

Now, instead, let's create one fish with the dispose flag checked, then force the GC to collect it. The resulting trace looks like:

Observe in this case, that both managed and unmanaged resources are disposed, AND that the destructor call is suppressed.
Problems

As described above, even though an object is disposed, there is nothing preventing you from continuing to use the object and any references you may have acquired to objects that it manages, as demonstrated by this code:
Collapse
private void btnRefTest_Click(object sender, System.EventArgs e)
{
ClassBeingTested cbt=new ClassBeingTested();
cbt.LoadImage("fish.jpg");
Image img=cbt.Image;
cbt.Dispose();
Trace.WriteLine("Image size=("+img.Width.ToString()+", "+img.Height.ToString()+")");
}

Of course, the result is:

Solutions

Ideally, one would want to assert or throw an exception when:
Dispose is called and managed objects are still referenced elsewhere
methods and accessors are called after the object has been disposed

Unfortunately (as far as I know) there is no way to access the reference count on an object, so it becomes somewhat difficult to determine if a managed object is still being referenced elsewhere. Besides require that the application "release" references, the best solution is to simply not allow another object to gain a reference to an internally managed object. In other words, the code:
Collapse
public Image Image
{
get {return img;}
}

should simply not be allowed in a "managing" class. Instead, the managing class should implement all the necessary support functions that other classes require, implementing a facade to the managed object. Using this approach, the application can throw an exception if the disposed flag is true--indicating that the object is still being accessed after it has technically been disposed of.
Conclusion - Unit Testing

The reason I went through this rigmarole is that I wanted to demonstrate the inadequacies of unit testing. For example, let us assume that the test class I described above does not implement IDisposable. Here we have an excellent example of how a single test on a class and its functions will succeed wonderfully, giving the illusion that all is well with a program that uses the class. But all is not well, because the class does not provide a means for the application to dispose of its managed resources, ultimately causing the entire computer system to bog down in fragmented memory and disk swapping.

This does not mean that unit testing is bad. It does however illustrate that it is far from a complete picture, and unit testing applications such as NUnit could use considerable growth in order to help the programmer automate more complex forms of unit testing.

And that, my friends, is going to be the topic of the next article.
Downloading The Demonstration Project

I have intentionally left out the "fish.jpg", being 3MB in size. Please edit the code and use your own JPG if you wish to play with the code.
License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here
About the Author
Marc Clifton

Architect
Interacx
United States

Member

转载于:https://www.cnblogs.com/ZJoy/archive/2010/12/17/1909601.html

【转载自codeproject】Another Look At IDisposable相关推荐

  1. 适用于 VS 2022 .NET 6.0(版本 3.1.0)的二维码编码器和解码器 C# 类库

    适用于 VS 2022 .NET 6.0(版本 3.1.0)的二维码编码器和解码器 C# 类库 本文转载自CodeProject上的一篇博文适用于 VS 2022 .NET 6.0(版本 3.1.0) ...

  2. c#笔试基础(转载)

    技术类面试.笔试题汇总 注:标明*的问题属于选择性掌握的内容,能掌握更好,没掌握也没关系. 下面的参考解答只是帮助大家理解,不用背,面试题.笔试题千变万化,不要梦想着把题覆盖了,下面的题是供大家查漏补 ...

  3. .net面试题[转载]

    1.简述private.protected.public.internal修饰符的访问权限. private:私有成员,在类的内部才可以访问. protected:保护成员,该类内部和继承类中可以访问 ...

  4. GitHub上整理的一些工具【转载】

    技术站点Hacker News:非常棒的针对编程的链接聚合网站Programming reddit:同上MSDN:微软相关的官方技术集中地,主要是文档类infoq:企业级应用,关注软件开发领域OSCh ...

  5. 搭建Git服务器教程转载

    1. 在Windows下使用ssh+msysgit客户端搭建Git服务器 http://www.codeproject.com/Articles/296398/Step-by-Step-Setup-G ...

  6. 在WCF中实现双工通信(转载)

    首先声明此文章是转载博客园蒋老师之作:http://www.cnblogs.com/artech/archive/2007/03/02/661969.html 双工(Duplex)模式的消息交互方式体 ...

  7. 转载 开发人员一定要加入收藏夹的网站

     开发人员一定要加入收藏夹的网站收藏 <script type="text/javascript"> document.body.oncopy = function() ...

  8. IDisposable实现的方法什么时候被执行的

    一,以什么是GC所认为的垃圾? 不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收 二,在仓储设计中,我们都知道非托管资源的手动释放,但继承的IDisposa ...

  9. 收藏——CodeProject - 使用特性(attributes)和激活机制来实现工厂模式

    收藏--CodeProject - 使用特性(attributes)和激活机制来实现工厂模式 分类: .NetDelphi2005-03-24 09:57496人阅读评论(0)收藏举报 原文 http ...

最新文章

  1. 微信小程序提示 出现脚本错误或者未正确调用 Page()
  2. (C++)1010 一元多项式求导 --需二刷
  3. 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)
  4. 返乡置业?多数人将掉入陷阱
  5. 慢慢聊Linux AIO
  6. JavaScript 中实现 sleep
  7. mysql数据库 支付_如何管理MySQL数据库?
  8. C#设置WebBrowser IE浏览器版本
  9. HDU-2829 Lawrence (DP+四边形不等式优化)
  10. 图书ISBN号码检验(洛谷P1055题题解,Java语言描述)
  11. 7-11 玩转二叉树 (25 分)
  12. 以锅炉安全为例,台账管理在安全建设中的作用
  13. NEW:5.9.4/Foxit PDF SDKfor ActiveX
  14. 微信、米聊等国内kik类手机通信录互动应用前景探讨
  15. 服务器系统管理维护,服务器操作系统的管理维护
  16. Java第十二周作业
  17. Web前端开发有哪些岗位职责 要掌握什么技能
  18. 自定义桌面右键菜单-Win 10 版
  19. exoplayer的media2扩展
  20. 2019高考(高中)数学必背重点公式大全

热门文章

  1. Mac下下载android4.2源码,进行源码调试
  2. 在EXCEL中如何将一列中的相同值的数据行找出来?
  3. 将COM+ Events进行到底[转]
  4. 微服务怎么部署到服务器的_浅谈微服务部署方案
  5. 技术干货 | jsAPI 方式下的导航栏的动态化修改
  6. 如何构建企业出海的“免疫力“?深入解读阿里云CDN安全能力
  7. 逸仙电商Seata企业级落地实践
  8. 云原生时代的“精益实践”:企业效能提升10倍“杀手锏
  9. 云效83行代码重构大师赛-码力全开,重启方舟
  10. 做过《战神》《死亡搁浅》的光子动捕专家,怎么理解动捕?