.Net Framework中,把资源分为托管资源和非托管资源两大类,

托管资源指可以通过.Net Frame垃圾回收器进行回收的资源,主要是指分配在托管堆上你的内存资源,这类资源的回收是不需要人工干预,.Net Framework的垃圾回收器会在合适的时刻进行回收,程序也可以主动调用GC.Collect()强制执行垃圾回收(但是不建议)。

非托管资源则是指不能被.Net Framework垃圾回收器回收的资源,主要包括以下几类:文件读写、窗口操作、网络连接、数据库连接、GDI画刷、图标等。针对这类资源,垃圾回收器能够跟踪其生存期,但不了解具体如何清理这些资源。针对这类资源,垃圾回收器在清理的时候回调用Object.Finalize()方法,该方法是虚方法,非托管对象需要重写方法来实现资源回收。

托管对象是不能重载Object.Finalize()方法,编译器会自动根据析构函数生成对应的Object.Finalize()方法,因此,当托管对象中使用到非托管资源时,需要在析构函数中释放该资料。

析构函数的定义如下(在方法名称为类名称前加了一个“~”):

    public class TestA
{
public string Name = "TestA";
~TestA()
{
Console.WriteLine("Dispose TestA");
}
}

由于析构函数是有垃圾回收器主动调用的,因此,调用该方法前,类包含的托管对象可能已经被主动回收了,此时再进行释放操作,可能会造成异常,因此,不建议在析构函数中释放托管资源。

垃圾回收器的操作时机是.NetFramework自己所决定的,它会在系统内存的占用和系统系统之间作一个平衡来决定何时出发,因此,对于非托管资源,这类资源属于宝贵资源,必须及时地释放掉,不能有垃圾回收器来决定何时释放。

.Net Framework中为回收资源,而定义了一个接口,IDisposable定义为:

     //
// 摘要:
// Defines a method to release allocated resources.
[ComVisible(true)]
public interface IDisposable
{
//
// 摘要:
// Performs application-defined tasks associated with freeing, releasing, or resetting
// unmanaged resources.
void Dispose();
}

任何包括非托管资源的类都需要继承此接口,并在接口方法中实现对托管资源和非托管资源的释放操作,同时在析构函数中实现对非托管资源的释放。

这么实现的好处就是:代码中显示调用Dispose()时,能够主动地释放资源(托管和非托管),垃圾回收器就会移除该对象不会执行回收操作(即不再执行Finalize()方法),从而提高了性能。而如果没有显示调用Dispose(),垃圾回收器也会在适当的时机调用Finalize()方法来释放非托管资源。

C#语言中using关键字作为语法糖出现,将非托管资源的使用包含在using()中使用,执行完成后会主动调用Dispose方法来释放资源。

基于性能考虑,应该降低使用析构函数来释放资源的使用频率,因此,没有析构函数的对象在垃圾处理器中直接删除,而包括析构函数的对象,则需要先执行析构函数,然后删除对象,增加了一次操作,会降低垃圾回收器的工作效率,从而影响性能。因此,对于非托管对象的释放,应该实现IDispose接口来回收资源,而不依赖垃圾回收器。

当前类使用new关键字创建了另一个类的实例时,当前类对新建的类实例的引用称为强引用,当新建类实例没有释放时,垃圾回收器则无法回收这个对象。只有将该引用释放的时候,垃圾回收器才会回收该对象。

 TestA a = new TestA();
a = null;
GC.Collect();
//当把变量a置为null,主动执行垃圾回收后就会回收该对象。

编程过程,我们会遇到这样的场景,持有一个对象实例的引用,这个实例比较庞大且创建成本不是太高,但是使用频率比较低。该情况下,可以使用WeakReference对这个实例进行包装,当需要使用当对象时,先调用WeakReference.IsAlive是否等于true或者Target不等于null,判断该对象实例是否存在,若存在则调用其Target并强制转换后使用,若不存在,则需要重新创建一个新的实例来使用。使用WeakReference包括的对象实例,垃圾回收器会释放该实例,回收其内存空间。所用,使用前必须判断其是否仍然存在。

C#基础知识回顾:1.由WeakReference想到对象的创建与销毁的更多相关文章

  1. Java基础知识回顾(一):字符串小结

    Java的基础知识回顾之字符串 一.引言 很多人喜欢在前面加入赘述,事实上去技术网站找相关的内容的一般都应当已经对相应知识有一定了解,因此我不再过多赘述字符串到底是什么东西,在官网中已经写得很明确了, ...

  2. java基础知识回顾之---java String final类普通方法

    辞职了,最近一段时间在找工作,把在大二的时候学习java基础知识回顾下,拿出来跟大家分享,如果有问题,欢迎大家的指正. /*     * 按照面向对象的思想对字符串进行功能分类.     *      ...

  3. C#基础知识回顾-- 反射(3)

    C#基础知识回顾-- 反射(3)   获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇“怎样在程序集中使用反射”, 其他没有什么可以写的了,前两篇主要是铺垫, ...

  4. C#基础知识回顾-- 反射(1)

    C#基础知识回顾-- 反射(1)   反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...

  5. C#基础知识回顾--线程传参

    C#基础知识回顾--线程传参 在不传递参数情况下,一般大家都使用ThreadStart代理来连接执行函数,ThreadStart委托接收的函数不能有参数, 也不能有返回值.如果希望传递参数给执行函数, ...

  6. python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。

    本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...

  7. Java基础知识回顾之七 ----- 总结篇

    前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...

  8. C++ 基础知识回顾总结

    一.前言 为啥要写这篇博客?答:之前学习的C和C++相关的知识,早就被自己忘到一边去了.但是,随着音视频的学习的不断深入,和C/C++打交道的次数越来越多,看代码是没问题的,但是真到自己操刀去写一些代 ...

  9. scrapy实战1,基础知识回顾和虚拟环境准备

        视频地址 https://coding.imooc.com/learn/list/92.html   一. 基础知识回顾     1. 正则表达式 1)贪婪匹配,非贪婪匹配 .*? 非贪婪 . ...

随机推荐

  1. Android中弹出dialog后无法捕捉back键

    一.需求 在Android开发过程中,弹出dialog后无法捕捉back键,点击back按键无响应. 二.解决方案 原因:弹出dialog后,activity失去焦点,dialog获得当前焦点. 解决 ...

  2. C#算法与数据结构之线性结构

    线性结构是什么? 线性结构是一种数据结构,它有一对一的关系,就像一个长对,一个接一个,特点是,除第一个元素和最后一个元素外,其它元素前后只有一个元素. 简单示例1: static void Main( ...

  3. 利用Module模块把构建的神经网络跑起来

    训练一个神经网络往往只需要简单的几步: 准备训练数据 初始化模型的参数 模型向往计算与向后计算 更新模型参数 设置相关的checkpoint 如果上述的每个步骤都需要我们写Python的代码去一步步实 ...

  4. Django富文本需要添加配置

    TINYMCE_DEFAULT_CONFIG = { 'theme': 'advanced', 'width': 600, 'height': 400, }

  5. HTTP 协议常见的状态码

    HTTP状态码负责表示客户端HTTP请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作. 状态码的类别: 记录在RFC2616上的HTTP状态码有40种,再加上WebDAV等的扩展,数量 ...

  6. Git的初步学习

    前言 感谢! 承蒙关照~ Git的初步学习 为什么要用Git和Github呢?它们的出现是为了用于提交项目和存储项目的,是一种很方便的项目管理软件和网址地址. 接下来看看,一家公司的基本流程图: 集中 ...

  7. 《http权威指南》读书笔记8

    概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...

  8. [Postman]历史(8)

    邮递员将您发送的所有请求存储在左侧边栏的“历史记录”视图中.您可以使用历史记录快速尝试各种请求,而不必浪费时间从头开始构建请求.您还可以通过单击请求名称来加载先前的请求. 如果您创建了一个帐户并登录P ...

  9. 史上最全阿里 Java 面试题总结

    以下为大家整理了阿里巴巴史上最全的 Java 面试题,涉及大量 Java 面试知识点和相关试题. JAVA基础 JAVA中的几种基本数据类型是什么,各自占用多少字节. String类能被继承吗,为什么 ...

  10. Kubernetes集群搭建之Etcd集群配置篇

    介绍 etcd 是一个分布式一致性k-v存储系统,可用于服务注册发现与共享配置,具有以下优点. 简单 : 相比于晦涩难懂的paxos算法,etcd基于相对简单且易实现的raft算法实现一致性,并通过g ...