参考书:《 visual C# 从入门到精通》 我们知道,创建对象要用 当变量 销毁对象并将内存归还给堆的过程称为垃圾回收。 用析构器可以在对象被垃圾回收时执行必要的清理。 构造器的语法是 注意以下几点: 编译器内部自动将构造器转换成对 编译器转换成如下的形式: C#中我们总是不能自己销毁对象,而是由 如果由程序员负责销毁对象,很有可能会遇到以下的情况: 而垃圾回收器可以做到以下几点担保: 注意,垃圾回收并不是在对象不再需要时立即进行。垃圾回收是一个代价较高的过程,所以只在觉得有必要时才会进行垃圾回收。 可以通过静态方法 垃圾回收器在它自己的线程中运行。它运行时应用程序中的其他线程将暂停,因为垃圾回收器可能需要移动对象并更新对象引用。 它的步骤大体如下: 一个类中包含析构器会使代码和垃圾回收过程变得复杂,同时会影响程序的运行速度。如果程序中不包含析构器,垃圾回收器就不需要将不可达对象放到 有点资源比较宝贵,用完后应该马上释放,这时就需要通过自己写的资源清理方法亲自释放资源。显式调用类的资源清理方法控制资源是释放的时机。 比如来自 上述代码的非常重要的一点是调用 为了解决上面的问题,可以在 但它存在几个缺点: 如: 它完全等价于前面用 而 实现 注意: 最后放上一个
第二部分 理解C#对象模型
第14章 使用垃圾回收和资源管理 文章目录
14.1 对象的生存期
new
关键字,Square mysquare = new Square();
new
实际上是分两步的:
new
操作从堆中分配原始内存,这个阶段无法进行干预new
操作将原始内存转换成对象:它必须初始化对象。可用构造器控制这一阶段mysquare
离开作用域时,它引用的对象就没有引用了,这样对象会被销毁,占用的内存被回收。对象的销毁也分来两步走: 1. `CLR`执行清理工作,可以写一个析构器来控制 2. `CLR`将对象占用的内存归还给堆,解除对象内存的分配。对这个阶段我们没有控制权。
14.1.1 编写析构器
CLR
可以自动清理对象使用的任何托管,所以很多时候时不需要自己写析构器的。但要是托管资源很大(如多维数组),就可以考虑对该资源的所有引用都设为null
,使资源能被立即清理。如果对象引用了非托管资源,析构器就更有用了。~
+类名,如下:class FileProcessor{ FileStream file=null; public FileProcessor(string fileName){ this.file=File.OpenRead(fileName); } ~FileProcessor(){ this.file.Close(); } }
struct
)Object.Finalize
方法的一个重写版本的调用。如:class FileProcessor{ -FileProcessor(){//你的代码} }
class FileProcessor{ protected override void Finalize(){ try{//你的代码 } finally{base.Finalize();} } }
14.1.2 为什么要使用垃圾回收器
CLR
在它认为合适的时间帮你做这件事。由于一个对象可能会有多个引用,CLR
必须跟踪所有的引用。对象的生存期不能和特定的引用变量绑定。只有在一个对象的所有引用都消失后才可以销毁该对象,回收其内存。
System.GC.Collect
在程序中调用垃圾回收器(回收过程时异步发生的),但不建议这样做。14.1.3 垃圾回收器的工作原理
freachable
的特殊队列中14.1.4 慎用析构器
freachable
队列并对他们进行“终结”。所以除非确实有必要,最好尽量避免使用析构器。同时要确定析构器不相互依赖或相互重叠。14.2 资源管理
14.2.1 资源释放方法
System.IO
命名空间中的TextReader
类,该类提供从顺序输入流中读取字符的机制。TextReader
包含虚方法Close
,它负责关闭流,这是一个资源清理方法。StreamReader
类从流中读取字符,StringReader
类从字符串中读取字符。这两个类都从TextReader
类派生,都重写了Close
方法。如使用StreamReader
类从文件中读取文本行并在屏幕上显示:TextReader reader =new StreamReader(filename); string line; while((line=reader.ReadLine())!=null){ Console.WriteLine(line); } reader.Close();
Close
方法来释放文件句柄以及相关资源。但有一个问题是它不是异常安全的。如果对ReadLine
或WriteLine
方法的调用抛出异常,对Close
的调用就不会发生了,这样可能会耗尽文件句柄资源,无法打开更多文件。14.2.2 异常安全的资源清理
finally
块中调用Close
方法:TextReader reader=new StreamReader(filename); try{ string line; while((line=reader.ReaderLine())!=null){ Console.WriteLine(line); } } finally{ reader.Close(); }
try
和finally
finally
块之后的作用域中,这意味着可能不小心使用一个已释放的资源14.2.3
using
语句和IDisposable
接口using
语句提供了一个脉络清晰的机制来控制资源的生存期。语法如下:using(type variable=initialzation){ ...; }
using(TextReader reader=new StreamReader(filename)){ string line; while((line=reader.ReadLine())!=null){ Console.WriteLine(line); } }
finally
块的形式:{ TextReader reader=new StreamReader(filename); try{ string line; while((line=reader.ReaderLine())!=null){ Console.WriteLine(line); } } finally{ reader.Close(); } }
using
语句定义了一个作用域。using
语句声明的类型必须实现IDisposable
接口。IDisposable
在System
命名空间中,只包含一个名为Dipose
的方法。namespace System{ interface IDisposable{ void Dispose(); } }
StreamReader
类实现了这个接口,它的Dispose
方法会调用Close
方法来关闭流。using
语句解决了finally
块可能出现的所有问题。14.2.4 从析构器中调用
Dispose
方法IDisposable
接口的示例如下:Class Example:IDisposable{ private Resource scarce; private bool dispose=false; ...; ~Example(){ this.Dispoable(false); } public virtual void Dispose(){ this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing){ if(!this.disposed){ if(disposing){ ...; } this.disposed=true; } } public void SomeBehavior(){ checkIfDisposed(); ...; } private void checkIfDisposed(){ if(this.disposed){ throw new ObjectDisposedException("示例:对象已经清理"); } } }
Dispose
方法可以安全的多次调用。变量disposed
指出方法以前是否运行过,这样防止在并发调用方法时资源被多次清理。方法只有在第一次运行才会清理资源Dispose
方法支持托管资源和非托管资源的清理Dispose
方法调用静态GC.SuppressFinalize
方法。该方法阻止垃圾回收器为这个对象调用析构器,因为对象已经终结了14.3 实现异常安全的资源清理
using
语句的示例:Calculator.cs
using System; using System.Collections.Generic; using System.Text; namespace C_14_3 { class Calculator:IDisposable { private bool disposed = false; public int Divide(int first,int second) { return first / second; } public void Dispose() { if (!disposed) { Console.WriteLine("Calculator being disposed"); } this.disposed = true; GC.SuppressFinalize(this); } public Calculator() { Console.WriteLine("Calculator being created"); } ~Calculator() { Console.WriteLine("Calculator being finalized"); this.Dispose(); } } }
Program.cs
using System; namespace C_14_3 { class Program { static void Main(string[] args) { using(Calculator calculator1=new Calculator()) { Console.WriteLine($"120/0={calculator1.Divide(120, 0)}"); } Console.WriteLine("Program finishing"); } } }
using
语句中故意引发异常,观察结果,程序最后还是调用了Dispose
方法来回收资源,运行结果为
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算