C#规范整理·资源管理和序列化

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#规范整理·资源管理和序列化相关的知识,希望对你有一定的参考价值。

源管理(尤其是内存回收)曾经是程序员的噩梦,不过在.NET平台上这个噩梦似乎已经不复存在。CLR在后台为垃圾回收做了很多事情,使得我们现在谈起在.NET上进行开发时,都会说还是new一个对象吧!回收?有垃圾回收器呢。其实并没有这么简单。
  对象序列化是现代软件开发中的一项重要技术,无论是本地存储还是远程传输,都会使用序列化技术来保持


资源管理


1.显式释放资源需继承接口IDisposable

C#中的每一个类型都代表一种资源,而资源又分为两类:

  • 托管资源 由CLR管理分配和释放的资源,即从CLR里new出来的对象。

  • 非托管资源 不受CLR管理的对象,如Windows内核对象,或者文件、数据库连接、套接字、COM对象等。

如果我们的类型使用到了非托管资源,或者需要显式地释放托管资源,那么就需要让类型继承接口IDisposable,这毫无例外。这相当于告诉调用者:类型对象是需要显式释放资源的,你需要调用类型的Dispose方法。,一个标准的继承了IDisposable接口的类型应该像下面这样去实现。这种实现我们称为Dispose模式:

C#规范整理·资源管理和序列化

C#规范整理·资源管理和序列化

承IDispose接口也为实现语法糖using带来了便利。在C#编码中,如果像下面这样使用using,编译器会自动为我们生成调用Dispose方法的IL代码:

C#规范整理·资源管理和序列化

 

2.即使提供了显式释放方法,也应该在终结器中提供隐式清理

在标准的Dispose模式中,我们注意到一个以~开头的方法,如下所示:

C#规范整理·资源管理和序列化

Copy


这个方法叫做类型的终结器。提供终结器的意义在于:我们不能奢望类型的调用者肯定会主动调用Dispose方法,基于终结器会被垃圾回收器调用这个特点,它被用作资源释放的补救措。

对于没有继承IDisposable接口的类型对象,垃圾回收器则会直接释放对象所占用的内存;而对于实现了Dispose模式的类型,在每次创建对象的时候,CLR都会将该对象的一个指针放到终结列表中,垃圾回收器在回收该对象的内存前,会首先将终结列表中的指针放到一个freachable队列中。同时,CLR还会分配专门的线程读取freachable队列,并调用对象的终结器,只有到这个时候,对象才会真正被标识为垃圾,并且在下一次进行垃圾回收时释放对象占用的内存。

可以看到,实现了Dispose模式的类型对象,起码要经过两次垃圾回收才能真正地被回收掉,因为垃圾回收机制会首先安排CLR调用终结器。基于这个特点,如果我们的类型提供了显式释放的方法来减少一次垃圾回收,同时也可以在终结器中提供隐式清理,以避免调用者忘记调用该方法而带来的资源泄漏。

注意1 在有的文档中,终结器也称做析构器。

注意2 如果调用者已经调用Dispose方法进行了显式地资源释放,那么,隐式释放资源(也就是终结器)就没有必要再运行了。
FCL中的类型GC提供了静态方法SuppressFinalize来通知垃圾回收器这一点。注意查看Dispose方法:

 
   
   
 
Copy

以上是关于C#规范整理·资源管理和序列化的主要内容,如果未能解决你的问题,请参考以下文章

C#开发微信小程序

C#规范整理·泛型委托事件

C#规范整理·泛型委托事件

C#常用代码片段备忘

HTTP API响应数据规范整理

C#规范整理·集合和Linq