您的位置:首页-> 资讯中心-> 其它文章-> 另类文集-> C++程序员容易犯的十个C#错误

另类文集

Txlist

本类阅读TOP10

Txtop

精品推荐
C++程序员容易犯的十个C#错误

作者:未知  来源:未知  加入时间:2005-2-2 宇宙软件下载

我们知道, C#的语法与C++非常相似,实现从C++向C#的转变,其困难不在于语言本身,而在于熟悉.NET的可管理环境和对.NET框架的理解。  

    尽管C#与C++在语法上的变化是很小的,几乎不会对我们有什么影响,但有些变化却足以使一些粗心的C++编程人员时刻铭记在心。在本篇文章中我们将讨论C++编程人员最容易犯的十个错误。

    错误1: 析构函数上的差异
几乎可以完全肯定地说,对于大多数C++编程人员而言,C#与C++最大的不同之处就在于垃圾收集。这也意味着编程人员再也无需担心内存泄露和确保删除所有没有用的指针。但我们再也无法精确地控制杀死无用的对象这个过程和时机。事实上,在C#中没有明确的Destructor。

    如果使用非托管资源,在不使用这些资源后,必须明确地释放它。对资源的隐性控制是由Finalize方法(在C#语言中,析构函数将被编译器转换为Finalize方法)提供的,当对象被销毁时,它就会被垃圾收集程序调用收回对象所占用的非托管资源。

Finalize方法应该只释放被销毁对象占用的非托管资源,而不应牵涉到其他托管对象。如果在程序中只使用了托管资源,那就无需也不应当为类编写Finalize方法,只有在非托管资源的处理中才会用到Finalize方法。直接调用一个对象的Finalize方法是绝对不允许的(除非是在派生类的Finalize中调用基类的Finalize。),垃圾收集程序会自动地调用Finalize。

    从语法上看,C#中的Destructor与C++非常相似,但其实它们是完全不同的。C#中的Destructor只是定义Finalize方法的捷径。因此,下面的二段代码是有区别的:

~MyClass()
{
    // 需要完成的任务
}

public override void Finalize()
{
    // 需要完成的任务

    base.Finalize();    // 这应该是本方法中的最后一步
}

第二段代码中要显示调用基类的Finalize方法是因为,编译器不会像析构函数那样帮我们自动调用基类的析构函数。

    错误2:Finalize?还是Dispose?
从上面的论述中我们已经很清楚,显性地调用Finalize是不允许的,它只能被垃圾收集程序调用。如果希望尽快地释放一些不再使用的数量有限的非托管资源(如文件句柄,数据库连接,网络连接等),则应该使用IDisposable接口,这一接口有个Dispose方法,它能够帮你完成这个任务。Dispose是无需等待Finalize被调用而能够释放非托管资源的唯一方法。

    如果已经使用了Dispose方法,则应当阻止垃圾收集程序再对相应的对象执行Finalize方法。为此,需要调用静态方法GC.SuppressFinalize,并将相应对象的指针传递给它作为参数,垃圾收集程序就不会在回收内存前对该对象调用Finalize方法。据此,我们能够得到如下的代码:

public void Dispose()
{
    // 完成清理操作

    // 通知GC不要再调用Finalize方法
    System.GC.SuppressFinalize(this);
}

public override void Finalize()
{
    Dispose();
    base.Finalize();
}

    对于有些对象,可能调用Close方法就更合适(例如,对于文件对象调用Close就比Dispose更合适),可以通过创建一个private属性的Dispose方法和public属性的Close方法,并让Close调用Dispose来实现对某些对象调用Close方法。



相关文章

相关软件