尽量在using中使用非托管资源

1.实现Dispose方法

2.提取一个受保护的Dispose虚方法,在该方法中实现具体的释放资源的逻辑

3.添加析构函数

4.添加一个私有的bool类型的字段,作为释放资源的标记

例子:

public class MyClass : IDisposable
{
/// <summary>
/// 模拟一个非托管资源
/// </summary>
private IntPtr NativeResource { get; set; } = Marshal.AllocHGlobal(100);
/// <summary>
/// 模拟一个托管资源
/// </summary>
public Random ManagedResource { get; set; } = new Random();
/// <summary>
/// 释放标记
/// </summary>
private bool disposed;
/// <summary>
/// 为了防止忘记显式的调用Dispose方法
/// </summary>
~MyClass()
{
//必须为false
Dispose(false);
}
/// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
public void Dispose()
{
//必须为true
Dispose(true);
//通知垃圾回收器不再调用终结器
GC.SuppressFinalize(this);
}
/// <summary>
/// 非必需的,只是为了更符合其他语言的规范,如C++、java
/// </summary>
public void Close()
{
Dispose();
}
/// <summary>
/// 非密封类可重写的Dispose方法,方便子类继承时可重写,当传入true时代表要同时处理托管资源和非托管资源;而传入false则只需要处理非托管资源即可
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
//清理托管资源
if (disposing)
{
if (ManagedResource != null)
{
ManagedResource = null;
}
}
//清理非托管资源
if (NativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(NativeResource);
NativeResource = IntPtr.Zero;
}
//告诉自己已经被释放
disposed = true;
}
}

当满足以下条件之一时,GC才会工作

1.系统具有较低的物理内存

2.由托管堆上已分配的对象使用的内存超出了可接受的范围

3.手动调用GC.Collect方法,但几乎所有的情况下,我们都不必调用,因为垃圾回收器会自动调用它。

静态变量不被释放(即使赋值为null也不会被编译器优化),是因为类型的静态字段一旦被创建,就被作为“根”存在,基本上不参与GC,所以GC始终不会认为它是个垃圾,而非静态字段则不会有这样的问题。

所以在实际工作当中,一旦我们感觉静态变量所占用的内存空间较大的时候,并且不会再使用,便可以将其置为null,最典型的案例就是缓存的过期策略的实现了,将静态变量置为null这或许不是很有必要,但这绝对是一个好的习惯,试想一个项目中,如果将某个静态变量作为全局的缓存,如果没有做过期策略,一旦项目运行,那么它所占的内存空间只增不减,最终顶爆机器内存,所以,有个建议就是:尽量地少用静态变量。

c#的IDisposable的更多相关文章

  1. 通过IEnumerable和IDisposable实现可暂停和取消的任务队列

    一般来说,软件中总会有一些长时间的操作,这类操作包括下载文件,转储数据库,或者处理复杂的运算. 一种处理做法是,在主界面上提示正在操作中,有进度条,其他部分不可用.这里带来很大的问题, 使用者不知道到 ...

  2. IDisposable的另类用法

    IDisposable是.Net中一个很重要的接口,一般用来释放非托管资源,我们知道在使用了IDisposable的对象之后一定要调用IDisposable.Dispose()方法,或者使用.Net提 ...

  3. C#中对IDisposable接口的理解

    http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...

  4. C# 中正确实现 IDisposable 接口

    作用 此接口的主要用途是释放非托管资源. 当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存. 但无法预测进行垃圾回收的时间. 另外,垃圾回收器对窗口句柄或打开的文件和流等非托管资源一无所知 ...

  5. using 语句中使用的类型必须可隐式转换为“System.IDisposable

    在使用 EF 出现 using 语句中使用的类型必须可隐式转换为“System.IDisposable 今天写在这里分享给大家 出现这样的问题,是因为没有引用  EntityFramework 这个程 ...

  6. C# ~ 由 IDisposable 到 GC

    IDisposable 接口 1. 托管资源和非托管资源   ·  托管资源  a.  CLR 控制和管理的内存资源,如程序中在 Heap 上分配的对象.作用域内的变量等:  b.  GC 机制实现自 ...

  7. C# IDisposable接口

    public class MyClass : IDisposable { public int a; public MyClass() { //构造 } public void Dispose() { ...

  8. 强制回收和IDisposable.Dispose方法

    如果某对象的 Dispose 方法被调用一次以上,则该对象必须忽略第一次调用后的所有调用. 如果对象的 Dispose 方法被多次调用,该对象一定不要引发异常. 除Dispose 之外的实例方法在资源 ...

  9. IDisposable接口

    C#中IDisposable接口的主要用途是释放非托管资源.当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存.但无法预测进行垃圾回收的时间.另外,垃圾回收器对窗口句柄或打开的文件和流等非托 ...

  10. 实现IDisposable接口的模式

    代码: public class Class2 : IDisposable { ~Class2() { Dispose(false); } public void Dispose() { Dispos ...

随机推荐

  1. SQLMap常用教程

    先安装 python环境(2.6.x或2.7版本) ,再将SQLMap 放在安装目录下 注意:sqlmap只是用来检测和利用sql注入点的,并不能扫描出网站有哪些漏洞,使用前请先使用扫描工具扫出sql ...

  2. ORACLE 求和(多列)

    SELECT SUM(列名),SUM(列名),SUM(列名),SUM(列名) FROM 表名

  3. C 结构体、位域

    参考链接:https://www.runoob.com/cprogramming/c-structures.html 结构体是干啥的 例如数组可以用来存储多个相同数据类型的数据项,结构体也是一种数据类 ...

  4. 第九届极客大挑战——Geek Chatroom(sql盲注)

    首先观察这个web应用的功能,可以任意留言,也可以搜索留言,当然我还用cansina扫描过网站,查看过源码,抓包查看过header等.没发现其他提示的情况下断定这就是个sql注入,可能存在的注入点呢, ...

  5. maven 学习---Maven快照

    大型软件应用程序通常由多个模块组成,这是多个团队工作于同一应用程序的不同模块的常见场景.例如一个团队工作负责应用程序的前端应用用户接口工程(app-ui.jar:1.0)),同时他们使用数据服务工程( ...

  6. Linux学习之常用命令(三)

    常用命令之工作目录 显示当前目录 pwd[选项] 切换目录 cd [文件路径] cd /root 注意:可以使用Tab键进行路径补齐 cd .. >>返回上次的目录 显示目录以及文件信息 ...

  7. appium---app输入中文

    在app自动化的过程中,都会遇到输入中文的问题,今天总结下app自动化如何输入中文 app输入中文 在启动app的时候在参数里面添加unicodeKeyboard和resetKeyboard后,运行代 ...

  8. RabbitMQ的几个常见问题

    1. 如何保证消息尽量发送成功? 问题描述: 如果没有启动消费者,重启了RabbitMQ服务,队列和消息都会丢失. 解决方案: 针对这个问题,有以下几个机制可以解决: 生产者确认: 持久化: 手动AC ...

  9. Mybatis-plus入门学习]

    需要的数据库建表语句: #创建用户表 CREATE TABLE user ( id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键', name VARCHAR ...

  10. Git分支管理(四)

    一.什么是分支 分支的好处: 同时并行推进多个功能开发,提高开发效率 各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任 何影响.失败的分支删除重新开始即可. 二.分支的操作 1. 创建 ...