当前位置: 首页 > 编程日记 > 正文

Finalize/Dispose/Destructor

我总是会搞混这些东西,还是写下来帮助记忆。

Finalize
即Object.Finalize(),C#中不允许使用Finalize,析构器就等价于Finalize。

Destructor
析构器(Destructor)是在对象没有被引用的时候,由CLR自动调用的。
任何包含非托管资源的类都必须定义析构器来释放这些资源,因为它们并不会在对象消亡时自动释放,而托管资源就可以。

Dispose方法
Dispose方法是IDisposable接口的实现方法,Dispose方法并不会被自动调用。

这里还有Dispose(bool)方法的概念,由于类的使用者或许会忘记使用Dispose()方法,并且析构器有可能二次执行析构操作,所以设计Dispose(bool)重载方法来判断并释放托管资源。合理的设计思想是,在Dispose()中使用Dispose(true)来显式释放托管资源和非托管资源,而在析构器中使用Dispose(false),只释放非托管资源(CLR会去自动调用托管资源的析构器)。在Dispose()方法中应使用GC.GC.SuppressFinalize()方法来阻止CLR调用析构器。

至于Close()方法,只是一种习惯名称,一般直接调用Dispose()方法。

来看MSDN里精辟的例子。

// Design pattern for the base class.
// By implementing IDisposable, you are announcing that instances
// of this type allocate scarce resources.
public class BaseResource: IDisposable
{
   
// Pointer to an external unmanaged resource.
   private IntPtr handle;
   
// Other managed resource this class uses.
   private Component Components;
   
// Track whether Dispose has been called.
   private bool disposed = false;

   
// Constructor for the BaseResource object.
   public BaseResource()
   {
      
// Insert appropriate constructor code here.
   }

   
// Implement IDisposable.
   
// Do not make this method virtual.
   
// A derived class should not be able to override this method.
   public void Dispose()
   {
      Dispose(
true);
      
// Take yourself off the Finalization queue 
      
// to prevent finalization code for this object
      
// from executing a second time.
      GC.SuppressFinalize(this);
   }

   
// Dispose(bool disposing) executes in two distinct scenarios.
   
// If disposing equals true, the method has been called directly
   
// or indirectly by a user's code. Managed and unmanaged resources
   
// can be disposed.
   
// If disposing equals false, the method has been called by the 
   
// runtime from inside the finalizer and you should not reference 
   
// other objects. Only unmanaged resources can be disposed.
   protected virtual void Dispose(bool disposing)
   {
      
// Check to see if Dispose has already been called.
      if(!this.disposed)
      {
         
// If disposing equals true, dispose all managed 
         
// and unmanaged resources.
         if(disposing)
         {
            
// Dispose managed resources.
            Components.Dispose();
         }
         
// Release unmanaged resources. If disposing is false, 
         
// only the following code is executed.
         CloseHandle(handle);
         handle 
= IntPtr.Zero;
         
// Note that this is not thread safe.
         
// Another thread could start disposing the object
         
// after the managed resources are disposed,
         
// but before the disposed flag is set to true.
         
// If thread safety is necessary, it must be
         
// implemented by the client.

      }
      disposed 
= true;         
   }

   
// Use C# destructor syntax for finalization code.
   
// This destructor will run only if the Dispose method 
   
// does not get called.
   
// It gives your base class the opportunity to finalize.
   
// Do not provide destructors in types derived from this class.
   ~BaseResource()      
   {
      
// Do not re-create Dispose clean-up code here.
      
// Calling Dispose(false) is optimal in terms of
      
// readability and maintainability.
      Dispose(false);
   }

   
// Allow your Dispose method to be called multiple times,
   
// but throw an exception if the object has been disposed.
   
// Whenever you do something with this class, 
   
// check to see if it has been disposed.
   public void DoSomething()
   {
      
if(this.disposed)
      {
         
throw new ObjectDisposedException();
      }
   }
}

// Design pattern for a derived class.
// Note that this derived class inherently implements the 
// IDisposable interface because it is implemented in the base class.
public class MyResourceWrapper: BaseResource
{
   
// A managed resource that you add in this derived class.
   private ManagedResource addedManaged;
   
// A native unmanaged resource that you add in this derived class.
   private NativeResource addedNative;
   
private bool disposed = false;

  
// Constructor for this object.
   public MyResourceWrapper()
   {
      
// Insert appropriate constructor code here.
   }

   
protected override void Dispose(bool disposing)
   {
      
if(!this.disposed)
      {
         
try
         {
            
if(disposing)
            {
               
// Release the managed resources you added in
               
// this derived class here.
               addedManaged.Dispose();         
            }
            
// Release the native unmanaged resources you added
            
// in this derived class here.
            CloseHandle(addedNative);
            
this.disposed = true;
         }
         
finally
         {
            
// Call Dispose on your base class.
            base.Dispose(disposing);
         }
      }
   }
}

// This derived class does not have a Finalize method
// or a Dispose method without parameters because it inherits 
// them from the base class.


有一个热传的对象复活(resurrection)的例子
public class Resurrection
{
    
public int Data;

    
public Resurrection(int data)
    {
        Data 
= data;
    }

    
~Resurrection()
    {
        Main.Instance 
= this;
    }
}

public class Main
{
    
public static Resurrection Instance;

    
public static void Main()
    {
        Instance 
= new Resurrection(1);
        Instance 
= null;
        GC.Collect();
        GC.WaitForPendingFinalizers();

        
// 看到了吗,在这里“复活”了。 
        Console.WriteLine(Instance.Data);
        Instance 
= null;
        GC.Collect();
        Console.ReadLine();
    }
}

还有一个弱引用的例子,弱引用的对象在回收以前还是可以被重复使用的。
public class Fat
{
    
public int Data;

    
public Fat(int data)
    {
        Data 
= data;
    }
}

public class MainClass
{
    
public static void Main()
    {
        Fat oFat 
= new Fat(1);
        WeakReference oFatRef 
= new WeakReference(oFat);

        
// 从这里开始,Fat对象可以被回收了。
        oFat = null;
        
if (oFatRef.IsAlive)
        {
            Console.WriteLine(((Fat) oFatRef.Target).Data);
        }
        
        GC.Collect();
        Console.WriteLine(oFatRef.IsAlive); 
// False 
        Console.ReadLine();
    }
}


参考:
http://msdn2.microsoft.com/zh-cn/library/fs2xkftw(VS.80).aspx
http://blog.csdn.net/sykpboy/archive/2005/04/11/342971.aspx

转载于:https://www.cnblogs.com/forck/archive/2008/04/16/1156343.html

相关文章:

linux 串口minicom配置使用

在minicom -s配置是记得取消硬件流控制。 1.minicom -o 配置文件 2.alias comminicom -o 配置文件 转载于:https://www.cnblogs.com/niceskyfly/p/5257713.html

POJ-1185 炮兵阵地 动态规划+状态压缩

由于递推的时候依赖于三个连续层的关系.一开始想着直接三重for循环,但是这里有个问题就是上一层的0位置上包括着上上层是0和1两种可能,而后者又对当前行有约束,因此该方法不行.当然有一个办法就是增加状态数,让状态能够表示是从1还是从0转移过来的.(这题有个解法是采用多进制的…

php字符串转换表达式,php处理字符串格式的计算表达式

有时候我们对每一种产品都有一个提成公式,而这个计算提成的公式是以字符串格式存在表中的当我们用这个计算公式时,他并不像我们写的:$a23*5;这样简单的能计算出结果,而它是个字符串所以,我们就必须把字符串转化为我们能…

JS函数式编程【译】5.2 函子 (Functors)

函子(Functors) 态射是类型之间的映射;函子是范畴之间的映射。可以认为函子是这样一个函数,它从一个容器中取出值, 并将其加工,然后放到一个新的容器中。这个函数的第一个输入的参数是类型的态射&#xff0…

[转]Introduction of iSCSI Target in Windows Server 2012

Introduction of iSCSI Target in Windows Server 2012 源地址:http://blogs.technet.com/b/filecab/archive/2012/05/21/introduction-of-iscsi-target-in-windows-server-2012.aspx The iSCSI Target made its debut as a free download for Windows 2008 R2 in A…

全国移动联通基站数据升级包(2013年1月基站升级包).rar

“全国移动联通基站数据升级包(2013年1月基站升级包).rar” 已经上传到CNBLOGS 地址:http://files.cnblogs.com/topwang-com/%E5%85%A8%E5%9B%BD%E7%A7%BB%E5%8A%A8%E8%81%94%E9%80%9A%E5%9F%BA%E7%AB%99%E6%95%B0%E6%8D%AE%E5%8D%87%E7%BA%A7%E5%8C%85(2013%E5%B9%…

php自动计算增长率,如何写sql计算增长率?

问题已有数据表(假定表名为t)time sale1999 4844904672000 651413668.92001 13713710082002 18177416252003 25053320952004 37654384862005 48177203842006 6083322598需要产生如下的数据表time sale …

我先了解一下博客园创建随笔/文章/日记的过程与三者的区别(隐私等级,是否审核等)...

我先了解一下博客园创建随笔/文章/日记的过程与三者的区别(隐私等级,是否审核等)转载于:https://www.cnblogs.com/Totooria-Hyperion/p/5260289.html

构建Java并发模型框架

2002 年 2 月 22 日 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦。线程间同步、数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误。另外,应用逻辑和线程逻辑纠缠…

Unity Note 1

1.把开始时间设定到播放完成的时间点,作为倒放的起点 animation["clip"].timeanimation["clip"].clip.length; animation["clip"].speed-1; animation.Play("clip"); 2.寻找场景中物体var door GameObject.Find(…

基于matlab的硅晶体模型,基于Matlab的图像处理技术识别硅太阳电池的缺陷

第 44 卷 第 7 期  2010 年 7 月 上 海 交 通 大 学 学 报 JOURNAL OF SHANGHAI J IAOTON G UNIVERSITY Vol. 44 No. 7   Jul. 2010   收稿日期 :20090908 作者简介 :柳效辉(19852) ,男 ,江西九江人 ,硕士生 ,主要从事光伏检测与光伏系统方面的研究. 徐  林(联系人) ,男 ,副…

spark- PySparkSQL之PySpark解析Json集合数据

PySparkSQL之PySpark解析Json集合数据 数据样本 12341234123412342|asefr-3423|[{"name":"spark","score":"65"},{"name":"airlow","score":"70"},{"name":"flume",&quo…

cmd库的导入Java,在cmd命令窗口导入第三方jar包来运行java文件

在cmd命令窗口导入第三方jar包来运行java文件,以下测试都是基于window环境,Linux环境没有测试。1、编译使用命令javac -cp或者javac -classpath本机测试:如下图所示,java文件路径为D:\workspace\demo,StringUtilsTest.java依赖了第…

JQuery 动态创建表单,并自动提交

前言:写这个是为了实现使用cookie进行自动登录的功能, 下面的代码是一个元素一个元素进行创建和赋值的, (可以尝试下将所有的html代码(form、input)全部拼好以后放到${ } 中,再进行提交。) submit的时候注意下写法&…

(转)利用ArcScene进行三维地形模拟

本文摘自:http://www.sunzx.net/archive/1109.html 在ArcGIS Desktop中,可用于三维场景展示的程序为ArcGlobe和ArcScene,由于两者的差别,在三维场景展示中适用的情况有所不同。ArcScene是一个适合于展示三维透视场景的平台&#x…

Android使用自定义View时:Error inflating class错误的原因。

当在布局文件里使用自定义的View的时候,出现Error inflating class错误的原因: 1、没有定义inflate需要的默认构造函数; eg:自定义View为TestView,需要定义TestView(Context context),TestView(Context context,AttributeSet set); 2、这是个…

oracle的表几种连接比较,几种表连接方式的使用场景

1)nested loopnested loop,指的是两个表连接时, 通过两层嵌套循环来进行依次的匹配, 最后得到返回结果集的表连接方法.select t1.owner,t1.object_name,t2.OBJECT_IDfrom test_tab1 t1,test_tab2 t2where t1.OBJECT_ID t2.OBJECT_IDand ROWNUM select *from test_t…

Ajax 完整教程 (转)

Ajax 完整教程第 1 页 Ajax 简介Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本文的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 —— 从总体概述到细节的讨论 ——…

.Net中如何操作IIS(源代码)

http://www.daima.com.cn/Info/3/Info20453/转载于:https://www.cnblogs.com/luoyuan/archive/2005/09/17/238986.html

Enterprise Library Configuration DAAB的使用

1.要试用DAAB,首先要引用两个类库 第一个是Enterprise Library Shared Library 这个类库是所有Enterprist Library都必须引用的类库,它提供所需的结构类型. 第二个是Enterprist Library Data Access Application Block 这个就是daab的核心类库. 2试用DAAB的第一个步骤就是配置a…

安装oracle后在cmd,在WINDOWS上安装ORACLE RAC的注意事项

在WINDOWS上安装ORACLE RAC的注意事项1、检查防火墙和杀毒软件如果不关掉防火墙,在安装CRS时,在"Oracle Clusterware Configuration Assistant"界面会提示(1)OUI-25031错误(2)dddb1 service OracleCSService in improper PENDING state, err(9…

Tessellation (曲面细分) Displacement Mapping (贴图置换)

DirectX 11 Tessellation (曲面细分)—什么是 Tessellation (曲面细分) ?它为什么可以起到如此关键的数据?随着近期人们对 DirectX 11 的议论纷纷,你可能已经听说了有关 DirectX 11 最大新特性 Tessellation (曲面细分) 的大量介绍。作为一个概念。 Tessellation …

java 第12课

/*Java是面向对象的程序设计语言.面向对象的思想是将客观事物都作为实体,而对象通过实体抽象得到.所谓实体抽象,就是对实体的某些特征进行概括,使其数字化、符号化;比如:李四同学,就是一个实体,我们关心他的这些特征:姓名、性别、年龄、身高、体重等特征,就会有李四、男、21、1…

鸽巢原理(The Pigeonhole Principle)(抽屉原理)

简单形式&#xff1a;若n1个物体放进n个盒子&#xff0c;那么至少有一个盒子包含两个或更多的物体。 应用&#xff1a;给定m个整数A1,A2,...,Am,存在整数k和l&#xff0c; 0 < k < l < m,使得Ak1 Ak2 &#xff0b; ... Al能够被m整除。即在A1&#xff0c;A2&…

oracle10g删除asm组,Oracle 10G RAC 删除已有节点

如果现在在RAC集群中有三个节点c1、c2、c3&#xff1a;如果想要卸载c3节点。1、在c1或者c2上删除c3实例运行dbca然后选择Oracle Real Application Clusters database选择Instance Management选择Delete an instance选择实例&#xff0c;填写用户名密码&#xff0c;Next选择c3: …

嵌入式linux学习笔记1—内存管理MMU之虚拟地址到物理地址的转化

一.内存管理基本知识 1.S3C2440最多会用到两级页表&#xff1a;以段的方式进行转换时只用到一级页表&#xff0c;以页的方式进行转换时用到两级页表。页的大小有三种&#xff1a;大页&#xff08;64KB&#xff09;&#xff0c;小页&#xff08;4KB&#xff09;&#xff0c;极小…

C# 最快的逐一打印斐波那契结果数列的算法

用这种方法就无需将数列中的每一个元素都计算一遍了&#xff01; 说多无谓&#xff0c;直接上代码吧&#xff01; private void button5_Click(object sender, EventArgs e) { FiBoNaQi f new FiBoNaQi(); f.numberToCount (Int16)numericUpDown1.Value; f.DoFiB…

WSS 代码执行的权限提升

WSS 代码执行的权限提升 概述: WSS 默认使用身份模拟执行代码&#xff0c;也就是说用当前登录的用户身份执行Web Part或者自定义应用程序的代码访问。在大多数情况下&#xff0c;这种机制能够准确并严格地控制了标准权限的用户他对特定网站资源和敏感数据的访问&#xff0c;这也…

Oracle数据库联邦,使用联邦数据库将oracle表迁移到DB2(9.7)中的脚本说明

由于兄弟项目组要测试&#xff0c;需要将oracle中的表迁移到db2中&#xff0c;操作步骤如下&#xff1a;#1 在windows数据库中建联邦数据库服务器\用户映射connect to sampleCREATE WRAPPER DRDA LIBRARY db2drda.dll;--创建DB2包装器CREATE WRAPPER NET8 LIBRARY db2net8.dll;…

HDU 5047 Sawtooth 高精度

题意&#xff1a; 给出一个\(n(0 \leq n \leq 10^{12})\)&#xff0c;问\(n\)个\(M\)形的折线最多可以把平面分成几部分。 分析&#xff1a; 很容易猜出来这种公式一定的关于\(n\)的一个二次多项式。 不妨设\(f(n)an^2bnc\)。 结合样例我们可以列出\(3\)个方程&#xff1a;\(f(…