内存有限,所以必须在不被占有的时候回收。
方法结束时值类型容易销毁。引用类型就不同。
析构函数~+类名;垃圾回收时执行任何整理。可以在任何线程上执行。
析构函数的限制:
1.不能在struct上声明;
2.不能有访问修饰符例如public;
3.不能带参数也不能接受参数,所以不可被重载,所以一个类最多一个析构函数;
4.析构函数是被自动调用,不可显示调用,不可被继承。
5.析构函数声明的标识符必须是类名;
6.析构函数声明包括extern修饰符时称外部析构函数,不提供任何实际的实现,函数体由一个分号组成。
7.非外部析构函数都都包含一个块。
任何代码不再使用某实例时,该实例就符合销毁条件。
销毁实例按照从派生程度最大到最小的顺序,调用继承链中的各个析构函数。
析构函数实际是重写了System.Object中的虚方法Finalize.
C#中永远不能亲自摧毁对象
垃圾回收器的保证:
每个对象都被摧毁;
每个对象都只被摧毁一次;
每个对象只有在该对象不存在任何引用才会摧毁;
目的:让程序员告别麻烦又易出错的清理工作。
可以调用静态方法System.GC.Collect()垃圾回收器;
但不建议这么做;
只有对象垃圾回收时才运行析构函数。含有析构函数的类会使代码和回收过程复杂影响性能。
更好的方法:
disposal方式--亲自释放
TextReader reader =new StreamReader(filename)
try{
string line;
while((line=reader.ReadLine())!=null)
finally
但这样做并不完美:
1.dispose多个资源会变得难以控制。
2.有时要修改代码(finally块中的引用不能为null)
3.不能创建解决方案的一个抽象,这意味方案难以理解,而你必须在需要该功能的任何地方重复代码。
4.对资源的引用保留在finally块之后的作用域中,这意味着可能不小心试图使用一个已经释放的资源。
using就是为解决这些而设计的;
可以将using语句作为一种明确异常安全的可靠的方式来保证一个资源总是被自动释放。这解决了人工try/finally中存在的问题。
需要dispose多个资源时有良好的扩展性;
不影响程序代码的逻辑;
对问题进行良好的抽象,避免重复性代码;
非常可靠;
注意此using非引入命名空间的using.
此using语法是
using(type variable=initialization) embeddedStstement
确保DataReader绝对Close
using(SqlDataReader dr=...)
}
}
using语句获取一个或多个资源,执行一个语句,然后处理这些资源。资源是实现IDisposable接口的类或结构。
正在使用资源的代码可以调用Dispose释放,如果不调用会由垃圾回收器处理。
using语句声明的局部变量【只读,不可ref out】,表达式必须是实现了IDisposable接口或可以隐式转化为IDisposable的一个类型。
using语句:获取-使用-处置
从析构函数中调用Dispose方法也许能保证它总是运行。
class Example:IDisposable
~example()
public virtual void Dispose();
finally
}
}
public void SomeBehavior()//示例方法
...
private void checkifdisposed(){
if(this.disposed)
{
throw new ObjectDisposedException("Example");
}
}
private Resource scarce;
private bool disposed=false;
}
注意
1.类实现了IDisposable
2.析构函数调用Dispose
3.Dispose方法是public可以随意调用
4.Dispose方法可以安全的多次调用。变量disposed指出方法以前是否运行过,只有第一次运行才会释放稀缺资源
5.Dispose方法调用静态的GC.SuppressFinalize方法。该方法防止垃圾回收器在这个对象上调用析构函数,因为对象现在已经finalized
6.类的所有常规方法都要检查对象是否disposed如果是就抛出异常