C# IDisposable的理解
C#里可以嵌入非托管代码,这就涉及到了这些代码资源的释放。以前总是看到别人的代码里那么写,也没有好好想想为什么,今天看了书,总结一下。
资源释放分为两种:
- 托管的
- 非托管的
两者的释放方式不一致:
- 没有非托管资源的,GC在运行时,会自动回收和释放;
- 含有非托管资源的,必须提供一个析构器,他们也会在内存里停留的时间会更长,最终被加入一个叫做finalization queue的结构,然后由GC在另一个线程释放;
实现IDispose接口是一种标准的释放资源的方式,正确使用会减少很多的bug和因为资源释放而引起的问题。正如上面所说,包含了非托管资源的代码,是必须提供一个析构器的。这样做的目的,是为了保证类的使用者,即使没有显式地调用Dispose方法,也可以正确地释放资源。
生产环境中的代码里,会有很多的继承,因此为了保证子类在调用时能够正确地执行父类的资源释放,在标准模式中,将真正的资源释放方法Dispose方法,抽象为一个virtual的方法,由子类去override,并在其中调用base的Dispose方法。
释放资源的Dispose方法,应该完成以下几件事(引用Effective C#)
- 释放所有的非托管资源;
- 释放所有的托管资源;
- 设定一个标志,标志资源是否已经销毁;对于销毁的对象,仍旧调用,则应抛异常;
- 跳过终结操作,调用GC.SuppressFinalize(this)方法。
以上,文字内容结束,基本的代码如下:
using System;
using System.Diagnostics; namespace Learn
{
class Program
{
private static int Cnt = ; static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = ; i < Cnt; i++)
{
IDisposeDerived de = new IDisposeDerived();
}
sw.Stop();
Console.WriteLine("total time is: " + sw.ElapsedMilliseconds);
Console.ReadLine();
}
} internal class IDisposeBase : IDisposable
{
// never add this unless unmanaged resources exist
// cauz this will add extra burdon and make negative influence on performance
//~IDisposeBase()
//{
// Dispose(false);
//} private bool AlreadyDisposed = false; public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} protected virtual void Dispose(bool shouldDisposeManagedReources)
{
if (AlreadyDisposed)
return;
if (shouldDisposeManagedReources)
{
// dispose the managed resources
// release the events
// etc.
}
// dispose the unmanaged resources // set the flag
AlreadyDisposed = true;
} public void MethodForPublic()
{
if (AlreadyDisposed)
throw new Exception("object has been disposed!");
// do the normal things
}
} internal class IDisposeDerived : IDisposeBase
{
//~IDisposeDerived()
//{
// Dispose(false);
//} private bool AlreadyDisposed = false; protected override void Dispose(bool shouldDisposeManagedReources)
{
if (AlreadyDisposed)
return;
if (shouldDisposeManagedReources)
{
// dispose managed resources
}
// dispose unmanaged resources // call the base's dispose method
base.Dispose(shouldDisposeManagedReources); // set the flag
AlreadyDisposed = true;
}
}
}
代码里增加了包含析构器的实现,可以对比一下,性能差异十分明显。
无析构器的实现结果:

有析构器的实现结果:

C# IDisposable的理解的更多相关文章
- C#中对IDisposable接口的理解
http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...
- 深入理解C#中的IDisposable接口
写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源,那么到底什么是资源,简单来讲,C#中的每一种类型都是一种资源,而资源又分为托管资源和非托管资源,那 ...
- 【转】C#中对IDisposable接口的理解
IDisposable接口定义:定义一种释放分配的资源的方法. .NET 平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无法对非托管资 ...
- 深入理解C#中的IDisposable接口(转)
转自:https://www.cnblogs.com/wyt007/p/9304564.html 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源, ...
- C# ~ 由 IDisposable 到 GC
IDisposable 接口 1. 托管资源和非托管资源 · 托管资源 a. CLR 控制和管理的内存资源,如程序中在 Heap 上分配的对象.作用域内的变量等: b. GC 机制实现自 ...
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- OWIN的理解和实践(二) – Host和Server的开发
对于开发人员来说,代码就是最好的文档,如上一篇博文所说,下面我们就会基于Kanata项目的一些具体调用代码,来进一步深入理解OWIN的实现和作用. 今天我们先针对Host和Server来实现一个简单的 ...
- 【转向Javascript系列】深入理解Generators
随着Javascript语言的发展,ES6规范为我们带来了许多新的内容,其中生成器Generators是一项重要的特性.利用这一特性,我们可以简化迭代器的创建,更加令人兴奋的,是Generators允 ...
- 【EntityFramework 6.1.3】个人理解与问题记录
前言 又是一个炎热夏日的晚上,开着空调听着音乐又开始了我们今天的博文.此文并不是ROM工具哪家强之类的引战贴,只是本文自己的一点看法和见解,望前辈看官有望斧正 声明 本文欢迎转载,原文地址:http: ...
随机推荐
- ETHREAD APC
ETHREAD APC <寒江独钓>内核学习笔记(4) 继续学习windows 中和线程有关系的数据结构: ETHREAD.KTHREAD.TEB 1. 相关阅读材料 <window ...
- memcpy的实现
memcpy的实现看起来貌似比较简单,但是也是有注意的地方! void *memcpy(void *dst, const void *src, size_t size) { //check argum ...
- 扩展Session机制
分布式缓存扩展Session机制 为什么要把Session放在缓存中 Session是我们常用的状态保持的对象,它通常会生成一个唯一的SessionId以Cookie的方式存在浏览器端,而Sess ...
- 解决Timer回调方法重复调用的问题
如果Timer的回调方法的执行时间很长,计时器可能在上个回调方法还没有完成的时候再次触发,如果我们只是想让一个回调方法执行完后再执行下一个回调方法,可以这样: private static Timer ...
- CSS中文字体的英文名称 – 前台开发必备
做什么用的?写过CSS的都晓得,一般用在font-family后面——为什么不用中文呢?有过一定开发经验的都晓得CSS里面用中文也是会乱码的,特别是没有中文字符集的浏览器,直接成了框框,用英文就可以解 ...
- cocos2dx在Eclipse下编译报错:Cannot find module with tag 'CocosDenshion/android' in import path
在Eclipse下编译cocos2dx项目,报错如下: Android NDK: jni/Android.mk: Cannot find module with tag 'CocosDenshion/ ...
- Redis系统学习 一、基础知识
1.数据库 select 1 select 0 2.命令.关键字和值 redis不仅仅是一种简单的关键字-值型存储,从其核心概念来看,Redsi的5种数据结构中的每一个都至少有一个关键字和一个值.在 ...
- 简单使用JSON,通过JSON 字符串来创建对象(二)
把 JSON 文本转换为 JavaScript 对象 JSON 最常见的用法之一,是从 web 服务器上读取 JSON 数据(作为文件或作为 HttpRequest),将 JSON 数据转换为 Jav ...
- 关于Java、Python、Go编程思想的不同
Go学习笔记 - 关于Java.Python.Go编程思想的不同 看了两周七牛团队翻译的<Go语言程序设计>,基本上领略到了Go语言的魅力.学习一个语言,语法什么的任何人都是很容易学会,难 ...
- IOS中KVO模式的解析与应用
IOS中KVO模式的解析与应用 最近老翁在项目中多处用到了KVO,深感这种模式的好处.现总结如下: 一.概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修 ...