<script type="text/javascript">google_ad_client = "pub-2048279401139630";google_ad_slot = "8856771542";google_ad_width = 728;google_ad_height = 90;document.write("<s"+"cript type='text/javascript' s"+"rc='http://pagead2.googlesyndication.com/pagead/show_ads"+"."+"js'></scr"+"ipt>");</script>
按照MSDN上所说
~ MyClass()
{
// Cleanup statements.
}
这个析构函数隐式地对对象的基类调用 Object.Finalize 方法
析构函数代码被隐式地转换为:
protected override void Finalize()
{
try
{
// Cleanup statements.
}
finally
{
base.Finalize();
}
}
对继承链中的所有实例递归地调用 Finalize 方法。
那好,也就是说写类的时候我只管写析构函数就是了,Finalize()函数我是不是最好不要去写呢?
不过~~仍然是可以写一个
public void Finalize() {...}
这样的函数出来的
但是写成
protected override void Finalize() {...}
就会抛出“编译器错误 CS0249”警告我不要重写object.Finalize。当然了,这也很正常,MS都已经说的很明白了,“无法使用 C# 或 C++ 编程语言的托管扩展来重写 Finalize 方法”
·那么,如果在一个类中析构函数和public void Finalize()同时存在,对于使用该类的app程序来说,释放该类的时候又会是什么结果呢~~~~~~
·第2个问题就是Dispose()和构造函数、Finalize()的关系又是怎样的呢?好像是继承的基类中有close方法的就要实现Dispose。
·对于以上3个函数,到底应该在什么情况下使用才是最恰当的呢?
第一个问题有意思,没有这么做过。但有一点,不应该重写Finalize()函数。按照面向对象的原理来看,如果你重写了一个基类函数但没有使用override,它将隐藏基类中的函数,可能产生非预期的结果与冲突。
所以第二个问题实际上应该是不考虑重写Finalize()方法前提下如何妥善使用Dispose()和析构函数(这是一个比较常见的问题了)。回答如下:
(1)首先要明白一个原则:资源在哪个类中被创建就应该在哪个类中清理。如果类中调用了其他基类中创建的资源,则应在基类中删除这些资源。然后看以下内容。
(2)析构函数:
析构函数是由垃圾回收器在清理对象时调用的。
因为.NET中的托管对象都是由垃圾回收器自动定期清理的,所以如果一个类中只有托管对象,则垃圾回收器在回收该对象时会同时一次性清理掉该类中创建的托管对象,此种情况下不要编写析构函数(情况A)。
如果一个类中创建使用了非托管资源(如数据库连接)(情况B),此时应该使用析构函数,但也只是作为忘记调用Dispose()函数的一种备份机制。换言之,此时,应该先掉用Dispose()函数来删除资源。
(3)Dispose()函数:
Dispose()函数由用户来调用。
在上面的情况A中,可以不调用Dispose()函数。但如果类中创建使用过一些较大的托管对象,最好尽快清除它们,此时可以在Dispose函数中删除它们,并由用户调用以尽快删除它们。
在情况B中,应该在Dispose()中删除非托管资源,并由用户调用Dispose()。此时,为防止垃圾回收器再次调用析构函数,应该在Dispose()中调用GC.SuppressFinalize(this)通知垃圾回收器,此对象已经不再需要执行析构函数以免重复执行。但如果用户忘记了调用Dispose(),则垃圾回收器仍然会执行析构函数,保证非托管资源会被清除。
以上对析构函数和Dispose()用法说明参看下面代码:
public class MyClass():IDisposable
{
private StreamReader sr;
private int connection;
......
public void Dispose()
{
Dispose(true);
GC.SuppressFinally(this);
}
protected virtual void Dispose(bool disposing)
{
if(disposing)
{ //清理托管资源
if(sr!=null)
{
sr.Close();
sr=null;
}
}
//清理非托管对象
CloseConnection(); //假设类中有这样一个函数用于清理connection这个非托管资源
}
~MyClass()
{
Dispose(false);//仅仅清理非托管资源,除此外不应编写其它代码。
}
.....
} <script type="text/javascript">google_ad_client = "pub-2048279401139630";google_ad_slot = "8856771542";google_ad_width = 728;google_ad_height = 90;document.write("<s"+"cript type='text/javascript' s"+"rc='http://pagead2.googlesyndication.com/pagead/show_ads"+"."+"js'></scr"+"ipt>");</script>
按照MSDN上所说
~ MyClass()
{
// Cleanup statements.
}
这个析构函数隐式地对对象的基类调用 Object.Finalize 方法
析构函数代码被隐式地转换为:
protected override void Finalize()
{
try
{
// Cleanup statements.
}
finally
{
base.Finalize();
}
}
对继承链中的所有实例递归地调用 Finalize 方法。
那好,也就是说写类的时候我只管写析构函数就是了,Finalize()函数我是不是最好不要去写呢?
不过~~仍然是可以写一个
public void Finalize() {...}
这样的函数出来的
但是写成
protected override void Finalize() {...}
就会抛出“编译器错误 CS0249”警告我不要重写object.Finalize。当然了,这也很正常,MS都已经说的很明白了,“无法使用 C# 或 C++ 编程语言的托管扩展来重写 Finalize 方法”
·那么,如果在一个类中析构函数和public void Finalize()同时存在,对于使用该类的app程序来说,释放该类的时候又会是什么结果呢~~~~~~
·第2个问题就是Dispose()和构造函数、Finalize()的关系又是怎样的呢?好像是继承的基类中有close方法的就要实现Dispose。
·对于以上3个函数,到底应该在什么情况下使用才是最恰当的呢?
第一个问题有意思,没有这么做过。但有一点,不应该重写Finalize()函数。按照面向对象的原理来看,如果你重写了一个基类函数但没有使用override,它将隐藏基类中的函数,可能产生非预期的结果与冲突。
所以第二个问题实际上应该是不考虑重写Finalize()方法前提下如何妥善使用Dispose()和析构函数(这是一个比较常见的问题了)。回答如下:
(1)首先要明白一个原则:资源在哪个类中被创建就应该在哪个类中清理。如果类中调用了其他基类中创建的资源,则应在基类中删除这些资源。然后看以下内容。
(2)析构函数:
析构函数是由垃圾回收器在清理对象时调用的。
因为.NET中的托管对象都是由垃圾回收器自动定期清理的,所以如果一个类中只有托管对象,则垃圾回收器在回收该对象时会同时一次性清理掉该类中创建的托管对象,此种情况下不要编写析构函数(情况A)。
如果一个类中创建使用了非托管资源(如数据库连接)(情况B),此时应该使用析构函数,但也只是作为忘记调用Dispose()函数的一种备份机制。换言之,此时,应该先掉用Dispose()函数来删除资源。
(3)Dispose()函数:
Dispose()函数由用户来调用。
在上面的情况A中,可以不调用Dispose()函数。但如果类中创建使用过一些较大的托管对象,最好尽快清除它们,此时可以在Dispose函数中删除它们,并由用户调用以尽快删除它们。
在情况B中,应该在Dispose()中删除非托管资源,并由用户调用Dispose()。此时,为防止垃圾回收器再次调用析构函数,应该在Dispose()中调用GC.SuppressFinalize(this)通知垃圾回收器,此对象已经不再需要执行析构函数以免重复执行。但如果用户忘记了调用Dispose(),则垃圾回收器仍然会执行析构函数,保证非托管资源会被清除。
以上对析构函数和Dispose()用法说明参看下面代码:
public class MyClass():IDisposable
{
private StreamReader sr;
private int connection;
......
public void Dispose()
{
Dispose(true);
GC.SuppressFinally(this);
}
protected virtual void Dispose(bool disposing)
{
if(disposing)
{ //清理托管资源
if(sr!=null)
{
sr.Close();
sr=null;
}
}
//清理非托管对象
CloseConnection(); //假设类中有这样一个函数用于清理connection这个非托管资源
}
~MyClass()
{
Dispose(false);//仅仅清理非托管资源,除此外不应编写其它代码。
}
.....
} <script type="text/javascript">google_ad_client = "pub-2048279401139630";google_ad_slot = "8856771542";google_ad_width = 728;google_ad_height = 90;document.write("<s"+"cript type='text/javascript' s"+"rc='http://pagead2.googlesyndication.com/pagead/show_ads"+"."+"js'></scr"+"ipt>");</script>