//这段代码来自官方示例,删除了其中用处不大的细节
using System;
using System.ComponentModel; /***
* 这个模式搞的这么复杂,目的是:不管使用者有没有手动调用Dipose函数,都能保证托管资源被正确释放,但非托管资源不管,因为非托管资源只能由用户保证
* 1,若用户手动调用Dispose(),则Dipose(true)被调用,托管与非托管一起释放了,同时告诉GC不要再执行析构函数
* 2,若用户没有手动调用Dispose()函数,则析构函数最终会被执行,其中调用了Dipose(false),保证托管资源被释放
*/
public class ConsoleMonitor : IDisposable
{
private bool disposed = false;
public ConsoleMonitor()
{
Console.WriteLine("The ConsoleMonitor class constructor.\n");
} // The destructor calls Object.Finalize.
~ConsoleMonitor()
{
Console.WriteLine("The ConsoleMonitor finalizer.\n"); // Call Dispose with disposing = false.
Dispose(false);
} public void Write()
{
Console.WriteLine("The Write method.\n");
} /***
* 不要写这个方法,会报错,因为它有BUG,很容易出错,官方推荐方式是用析构函数来替代此方法
* 原理上来说,此方法是继承了IDispose的类在析构时会被调用的,它最初的设计目的等同于析构函数
*/
//void Finalize()
//{ //} //给外部手动调用的,方法名可以任意
public void Dispose()
{
Console.WriteLine("TThe Dispose method.\n"); Dispose(true); //告诉GC管理器,当GC执行时不要再调用此对象的析构函数(其中有Dispose(false)),因为我们自己已在Dispose(true)中已进行了dipose(false)的操作
GC.SuppressFinalize(this);
} /***给析构函数(或finalize)调用的,函数签名必须这样
* 注意finalize已废弃,见如上说明
* disposing:当我们自己调用时传true,当系统调用时为false
* true和false主要为了区别销毁托管资源与非托管资源
*/
private void Dispose(bool disposing)
{
Console.WriteLine("The Dispose({0}) method.\n"); // Execute if resources have not already been disposed.
if (!disposed)
{
// If the call is from Dispose, free managed resources.
if (disposing)
{
Console.Error.WriteLine("Disposing of managed resources.");
}
// Free unmanaged resources.
Console.WriteLine("Disposing of unmanaged resources.");
}
disposed = true;
}
} public class Example
{
public static void Main()
{
Console.WriteLine("ConsoleMonitor instance....");
ConsoleMonitor monitor = new ConsoleMonitor();
monitor.Write();
monitor.Dispose();
}
}
// If the monitor.Dispose method is not called, the example displays the following output:
// ConsoleMonitor instance....
// The ConsoleMonitor class constructor.
// The Write method.
// The ConsoleMonitor finalizer.
// The Dispose(False) method.
// Disposing of unmanaged resources.
//
// If the monitor.Dispose method is called, the example displays the following output:
// ConsoleMonitor instance....
// The ConsoleMonitor class constructor.
// The Write method.
// The Dispose method.
// The Dispose(True) method.
// Disposing of managed resources.
// Disposing of unmanaged resources.

具体理论参考官方解析:

Implementing a Dispose method

有关Dispose,Finalize,GC.SupressFinalize函数-托管与非托管资源释放的模式的更多相关文章

  1. C#中Dispose,finalize,GC,析构函数区别

    释放类所使用的未托管资源的两种方式:  1.利用运行库强制执行的析构函数,但析构函数的执行是不确定的,而且,由于垃圾收集器的工作方式,它会给运行库增加不可接受的系统开销. 2.IDisposable接 ...

  2. [.net 面向对象程序设计进阶] (8) 托管与非托管

    本节导读:虽然在.NET编程过程中,绝大多数内存垃圾回收由CLR(公共语言运行时)自动回收,但也有很多需要我们编码回收.掌握托管与非托管的基本知识,可以有效避免某些情况下导致的程序异常. 1.什么是托 ...

  3. C# using 三种使用方式 C#中托管与非托管 C#托管资源和非托管资源区别

    1.using指令.using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到. ...

  4. C#的托管与非托管大难点

    托管代码与非托管代码 众所周知,我们正常编程所用的高级语言,是无法被计算机识别的.需要先将高级语言翻译为机器语言,才能被机器理解和运行.在标准C/C++中,编译过程是这样的:源代码首先经过预处理器,对 ...

  5. C#的三大难点之二:托管与非托管

    相关文章: C#的三大难点之前传:什么时候应该使用C#?​C#的三大难点之一:byte与char,string与StringBuilderC#的三大难点之二:托管与非托管C#的三大难点之三:消息与事件 ...

  6. C# 托管和非托管混合编程

    在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难.   最直接的实现托管与非托管编程的方法就是 ...

  7. NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配

    在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...

  8. [转]C# 之DLL调用(托管与非托管)

    每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基于win 32平台开发的DLL,activeX ...

  9. Oracle Data Provider for .NET的使用(托管与非托管(一))

    目录 简单的概述 简单的使用 非托管系统要求 托管驱动系统要求 其它的注意事项 ODP.NET版本说明 安装ODP.NET 安装非托管驱动 非托管驱动绿色配置 简单的概述 ODP.NET的含义是 Or ...

随机推荐

  1. GUI程序原理分析

    1,Qt 是一套跨平台的程序设计库,这套程序设计库主要用于 GUI 方面的程序设计开发,所以本系列博文主要是利用C++介绍 GUI 程序设计技术: 2,命令行应用程序: 1,命令行应用程序的特点(Co ...

  2. 【LGR-065】洛谷11月月赛 III Div.2

    临近$CSP$...... 下午打了一发月赛,感觉很爽. 非常菜的我只做了前两题......然而听说前两题人均过...... 写法不优秀被卡到$#1067$...... T1:基础字符串练习题: 前缀 ...

  3. MyBatis插入并返回id技巧

    1, 使用返回插入id的值,这个值即是当前插入的id

  4. 如何将数据库导入到本地MySQL

    有两个方法:(1)在MySQL的客户端进行导入,比如: http://jingyan.baidu.com/article/6dad507517c11aa123e36ea0.html (2)方法:常用s ...

  5. jquery TAB切换小插件

    //tab切换 ;(function($, window, document, undefined) { $.fn.tab = function(options) { var defaults = { ...

  6. npm学习(一)之安装、更新以及管理npm版本

    安装npm 安装前须知: npm是在Node中编写的,因此需要安装Node.js才能使用npm.可以通过Node.js网站安装npm,或者安装节点版本管理器NVM. 如果只是想开始探索npm,使用No ...

  7. 【问题解决方案】Linux中命令useradd与adduser的区别

    参考链接: useradd与adduser的区别 useradd与adduser:创建新的用户 CentOs: useradd与adduser是没有区别的 都是在创建用户,在home下自动创建目录,没 ...

  8. 使用GET与POST方式获取html数据

    抓取网站数据解析的工作,其中,使用到GET和POST方法获取html数据. 使用GET方式: /** * 使用get方式获取html数据 * * @param strURL(需要访问的网站) * @r ...

  9. vue梳理(2)

    -app.vue作为根组件被挂载到index.html文件里,其他的所有组件都是在app.vue组件里做文章. 展示给用户的就是app.vue里的内容,你觉得删的没有内容了但实际还有很多是因为什么呢? ...

  10. linux MySQL 初始化数据库

    #创建数据目录并且初始化 /bin/mysql_install_db –user=mysql