C 编程人员容易犯的10个C#错误

2008-02-23 05:32:37来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

我们知道,C#的语法和C 很相似,实现从C 向C#的转变,其困难不在于语言本身,而在于熟悉.net的可管理环境和对.NET框架的理解。尽管C#和C 在语法上的变化是很小的,几乎不会对我们有什么影响,但有些变化却足以使一些粗心的C 编程人员时刻铭记在心。在本篇文章中我们将讨论C 编程人员最容易犯的十个错误。

陷阱1: 没有明确的结束方法

几乎能够完全肯定地说,对于大多数C 编程人员而言,C#和C 最大的不同之处就在于碎片收集。这也意味着编程人员再也无需担心内存泄露和确保删除任何没有用的指针。但我们再也无法精确地控制杀死无用的对象这个过程。事实上,在C#中没有明确的destructor。

假如使用非可管理性资源,在不使用这些资源后,必须明确地释放他。对资源的隐性控制是由Finalize方法(也被称为finalizer)提供的,当对象被销毁时,他就会被碎片收集程式调用收回对象所占用的资源。finalizer应该只释放被销毁对象占用的非可管理性资源,而不应牵涉到其他对象。假如在程式中只使用了可管理性资源,那就无需也不应当执行Finalize方法,只有在非可管理性资源的处理中才会用到Finalize方法。由于finalizer需要占用一定的资源,因此应当只在需要他的方法中执行finalizer。直接调用一个对象的Finalize方法是绝对不允许的(除非是在子类的Finalize中调用基础类的Finalize。),碎片收集程式会自动地调用Finalize。

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

~MyClass()

{ // 需要完成的任务

}

MyClass.Finalize() {// 需要完成的任务

base.Finalize();

}

错误2:Finalize和Dispose使用谁?

从上面的论述中我们已很清楚,显性地调用finalizer是不允许的,他只能被碎片收集程式调用。假如希望尽快地释放一些不再使用的数量有限的非可管理性资源(如文档句柄),则应该使用IDisposable界面,这一界面有个Dispose方法,他能够帮您完成这个任务。Dispose是无需等待Finalize被调用而能够释放非可管理性资源的方法。

假如已使用了Dispose方法,则应当阻止碎片收集程式再对相应的对象执行Finalize方法。为此,需要调用静态方法GC.SuppressFinalize,并将相应对象的指针传递给他作为参数,Finalize方法就能调用Dispose方法了。据此,我们能够得到如下的代码:

public void Dispose()

{

// 完成清理操作

// 通知GC不要再调用Finalize方法

GC.SuppressFinalize(this);

}

public override void Finalize() {

Dispose(); base.Finalize();

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

由于不能确定一定会调用Dispose,而且finalizer的执行也是不确定的(我们无法控制GC会在何时运行),C#提供了一个Using语句来确保Dispose方法会在尽可能早的时间被调用。一般的方法是定义使用哪个对象,然后用括号为这些对象指定一个活动的范围,当碰到最内层的括号时,Dispose方法就会被自动调用,对该对象进行处理。

using System.Drawing;

class Tester

{

public static void Main()

{

using (Font theFont = new Font("Arial", 10.0f))

{

//使用theFont对象

} // 编译器将调用Dispose处理theFont对象

Font anotherFont = new Font("Courier",12.0f);

using (anotherFont)

{

// 使用anotherFont对象

} // 编译器将调用Dispose处理anotherFont对象 }

}



在本例的第一部分中,Font对象是在Using语句中创建的。当Using语句结束时,系统就会调用Dispose,对Font对象进行处理。在本例的第二部分,Font对象是在Using语句外部创建的,在决定使用他时,再将他放在Using语句内,当Using语句结束时,系统就会调用Dispose。Using语句还能防止其他意外的发生,确保系统一定会调用Dispose。

错误3:C#中的值型变量和引用型变量是有区别的

C 相同,C#也是一种强类型编程语言。C#中的数据类型被分为了二大类:C#语言本身所固有的数据类型和用户自定义数据类型,这一点也和C 相似。

此外,C#语言还把变量分为值类型和引用类型。除非是被包含在一个引用类型中,值类型变量的值保留在栈中,这一点和C 中的变量很相似。引用类型的变量也是栈的一种,他的值是堆中对象的地址,和C 中的指针很地相似。值类型变量的值被直接传递给方法,引用型变量在被作为参数传递给方法时,传递的是索引。类和界面能够创建引用类变量,但需要指出的是,结构数据类型是C#的一种内置数据类型,同时也是一种值型的数据类型。错误4:注意隐性的数据类型转换

Boxing和unboxing是使值型数据类型被当作索引型数据类型使用的二个过程。值型变量能够被包装进一个对象中,然后再被解包回值型变量。包括内置数据类型在内的任何

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 在C 中实现.NET风格的委托

下一篇: 关于C语言的学习方法