彭宁新的网站系统
当前位置:中国站长 > C#    
程序开发C语言Java/JSP移动开发汇编语言C#C++VBDelphi
CGI论坛SilverlightActionScript
C#中的析构函数
整理时间:12-10-2009 整理人员:夏天   ( 得分:5 )
阅读人次:1645
在企业应用开发世界,性能,灵活性和安全性是最重要的。我作为一个VC++程序员开始我的职业生涯,并且在一个晴朗的早晨,我被转到了Web开发部。像每个C++程序员一样,我也很失落。我想每个像Tom,Dick甚至Harry能用HTML编程。然而,不久我就发现真正的挑战是生产高性能的,灵活的可靠的应用程序。综上所述,Web环境松耦合的,不分国界的本质将使你永远神往。
为了制作高性能的灵活的应用程序,用最优化的方式使用你的资源是至关重要的。一个技巧是尽可能晚地使用你的资源并且在使用后尽快释放它。我在这里的意图是描述在C#中的对象清除机制。
解构器
我们知道,‘解构器’被用来清除类的事例。当我们在C#中使用解构器是,我们必须记住以下几点:
一个类只能有一个解构器。
解构器不能被继承或重载。
解构器不能被调用。他们是自动被(编译器)调用的。
解构器不能带修饰或参数。
下面是类MyClass解构器的一个声明:
~ MyClass()
// Cleaning up code goes here
}

程序员不能控制解构器何时将被执行因为这是由垃圾收集器决定的。垃圾收集器检查不在被应用程序使用的对象。它认为这些条件是符合清楚的并且收回它们的内存。解构器也在程序退出时被调用。当解构器执行时其背后所发生的那一幕是解构器隐式调用对象基类的Object.Finalize方法。因此上述解构器代码被隐含转化成:
protectedoverridevoid Finalize()
{
try
{
// Cleaning up .
}
finally
{
base.Finalize();
}
}

现在,让我们看一个解构器怎样被调用的例子。我们有三个类A,B和C。B派生自A,C派生自B。每个类有它们自己的构造器和解构。在类App的main函数中,我们创建C的对象。
  1. using System;   
  2. namespace Example   
  3. {   
  4.      class A   
  5.      {   
  6.           public A()   
  7.           {   
  8.                 Console.WriteLine("Creating A");   
  9.           }   
  10.           ~A()   
  11.           {   
  12.                 Console.WriteLine("Destroying A");   
  13.           }   
  14.      }   
  15.      class B : A   
  16.      {   
  17.           public B()   
  18.           {   
  19.                 Console.WriteLine("Creating B");   
  20.           }   
  21.           ~B()   
  22.           {   
  23.                 Console.WriteLine("Destroying B");   
  24.           }   
  25.      }   
  26.      class C : B   
  27.      {   
  28.           public C()   
  29.           {   
  30.                 Console.WriteLine("Creating C");   
  31.           }   
  32.           ~C()   
  33.           {   
  34.                 Console.WriteLine("Destroying C");   
  35.           }   
  36.      }   
  37.      class App   
  38.      {   
  39.           public static void Main()   
  40.           {   
  41.                 C c = new C();   
  42.                 Console.WriteLine("Object Created ");   
  43.                 Console.WriteLine("Press enter to Destroy it");   
  44.                 Console.ReadLine();    
  45.                 c = null;    
  46.                 GC.Collect();   
  47.                 Console.Read();   
  48.           }   
  49.      }   
  50. }  
正如我们预料的,基类的构造器将会被执行并且程序会等待用户按‘enter’。当这个发生,我们把类C的对象置为null.但解构器没有被执行..!!??正像我们所说的,程序员无法控制解构器何时被执行因为这是由垃圾搜集器决定的。但程序退出时解构器被调用了。你能通过重定向程序的o/p到文本文件来检查这个。我将它输出在这里。注意到基类的解构器被调用了,因为在背后base.Finalize()被调用了。
Creating A
Creating BCreating CObject Created Press enter to Destroy itDestroying CDestroying BDestroying A 所以,如果一旦你使用完对象你就想调用解构器,你该怎么做?有两个方法:调用垃圾搜集器来清理。
实现IDisposable的Dispose方法。
调用垃圾搜集器
你能通过调用GC.Collect方法强制垃圾搜集器来清理内存,但在大多数情况下,这应该避免因为它会导致性能问题。在上面的程序中,在GC.Collect()处移除注释。编译并运行它。现在,你能看到解构器在控制台中被执行了。
实现IDisposable接口
IDisposable 接口包括仅有的一个公共方法,其声明为void Dispose()。我们能实现这个方法来关闭或释放非托管资源如实现了这个接口的类事例所控制的文件,流,和句柄等。这个方法被用做所有任务联合对象的资源释放。当实现了这个方法,对象必须寻求确保所有拥有的资源被继承结构中关联的资源也释放(不能把握,翻不出来)。
class MyClass:IDisposable
{publicvoid Dispose() { //implementation }} 当我们实现了IDisposable接口时,我们需要规则来确保Dispose被适当地调用。
联合使用解构器和IDisposable接口
  1. public class MyClass : IDisposable   
  2. {   
  3.      private bool IsDisposed = false;   
  4.      public void Dispose()   
  5.      {   
  6.           Dispose(true);   
  7.           GC.SupressFinalize(this);   
  8.      }   
  9.      protected void Dispose(bool Diposing)   
  10.      {   
  11.           if (!IsDisposed)   
  12.           {   
  13.                 if (Disposing)   
  14.                 {   
  15.                      //Clean Up managed resources     
  16.                 }   
  17.                 //Clean up unmanaged resources    
  18.           }   
  19.           IsDisposed = true;   
  20.      }   
  21.      ~MyClass()   
  22.      {   
  23.           Dispose(false);   
  24.      }   
  25. }  
在这里重载了Dispose(bool)来做清理工作,并且所有的清理代码都仅写在这个方法中。这个方法被解构器和IDisposable.Dispose()两着调用。我们应该注意Dispose(bool)没有在任何地方被调用除了在IDisposable.Dispose()和解构器中。
当一个客户调用IDisposable.Dispose()时,客户特意地想要清理托管的和非托管资源,并且因此完成清理工作。有一件你必须注意的事情是我们在清理资源之后立即调用了GC.SupressFinalize(this)。这个方法通知垃圾搜集器不需要调用解构器,因为我们已经做了清理。
注意上面的例子,解构器使用参数false调用Dispose。这里,我们确信垃圾搜集器搜集了托管资源。我们仅仅做非托管资源的清理。
结论
尽管如此我们花费一些时间实现IDisposable接口,如果客户不能合适地调用它们会怎样?为此C#有一个酷的解决方案。‘using’代码块。它看起来像这样:
using (MyClass objCls =new MyClass()){}

当控制从using块通过成功运行到结束或者抛出异常退出时,MyClass的IDispose.Dispose()将会被执行。记住你例示的对象必须实现System.IDisposable接口。using语句定义了哪个对象将被清除的一个范围。
 
操作系统
Windows系列苹果
Linux架设服务器
数据库
MySqlSQL Server
ACCESSVFP
SybaseDB2
Oracle
综合应用
网络技术黑客技术
电脑故障病毒安全
程序开发
C语言Java/JSP
移动开发汇编语言
C#C++
VBDelphi
CGI论坛
SilverlightActionScript
平面&三维
PhotoShopFlash
3DmaxCAD
CorelDraw
网页设计
JavascriptVML教程
Php语言AJAX
XMLASP
ASP.NETCss
HTML语法Dom
电脑基础
域名知识虚拟主机
网站知识VPS知识
主机知识服务器架设
邮箱知识IDC增值服务
最新推荐
  • C#中的析构函数
  • 防止对 Visual Basic .NET...
  • C# 2.0:使用匿名方法、迭...
  • .net中内存占用的问题
  • ASP.NET缓存:方法和最佳实...
  • UBB(c#完整版)
  • C#实现web信息自动抓取
  • C#实现的18位身份证格式验...
  • 本类热门
  • sideBar控件的使用方法
  • C# 2.0:使用匿名方法、迭...
  • .net中内存占用的问题
  • 防止对 Visual Basic .NET...
  • ASP.NET缓存:方法和最佳实...
  • C#中的析构函数
  • UBB(c#完整版)
  • C#实现web信息自动抓取

  • 粤ICP备12087766号   |  

    粤公网安备 44139902100106号