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

我们知道,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对象 }
}

时间: 2025-01-19 09:34:43

C++编程人员容易犯的10个C#错误的相关文章

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

c++|编程   C++编程人员容易犯的10个C#错误 我们知道, C#的语法与C++非常相似,实现从C++向C#的转变,其困难不在于语言本身,而在于熟悉.NET的可管理环境和对.NET框架的理解. 尽管C#与C++在语法上的变化是很小的,几乎不会对我们有什么影响,但有些变化却足以使一些粗心的C++编程人员时刻铭记在心.在本篇文章中我们将讨论C++编程人员最容易犯的十个错误. 陷阱1: 没有明确的结束方法 几乎可以完全肯定地说,对于大多数C++编程人员而言,C#与C++最大的不同之处就在于碎片收

设计师最容易犯的10个Photoshop错误

  设计师最容易犯的10个Photoshop错误         一.使用错误的图像模式 操作菜单变成灰色?颜色看起来不对劲?当你遇到这些问题的时候,应该停下来,不要再编辑.这些可能就是使用错误的图像模式而引起的问题.在主菜单中选择"图像>模式",在这里确保选择正确的图像模式.如果你不知道应该选择哪种图片模式,那么请选择RGB模式吧!因为有99%的机会,图像采用RGB模式比较适合,原因如下: 任何网络图片都会以RGB模式显示图片; 数码图片以RGB模式被捕捉,因此应在RGB模式下

我在学习编程中常犯的两个最大错误

一年前,我刚从大学毕业并且决定踏入社会.我有很多初始的想法并想将它们实现,但我不懂编程. 听从Yipit 联合创始人Vin Vacant 的建议之后,我开始自学编程. 现在我终于学了足够多的知识来自己实现产品原型,一路走来,非常坎坷.如果你在跟我同样的路上,我希望你能避免犯跟我同样的错误. 错误1:我花了太多时间学习那些我不是特别需要的东西上 有如此多的技术,又有那么多的相互矛盾的观点以至于你很难判断什么是重要的,我根本就不知道如何开始.在Hacker News. Quora. Stack Ov

(译)开发人员经常犯的8个设计错误

设计师在抱怨开发人员不尊重Web标准,后台开发人员在抱怨为什么不可以增加一个空格.PM在抱怨为什么项目总是因为那些看似简单的问题而延期--如何才能提高后台开发人员与设计师以及前端开发工程师的合作效率?相信很多网站或软件开发公司都越到类似的问题. 从UED的角度而言,我们的天职是追求用户体验.我们应该尽力坚持自己应该坚持的东西.白鸦曾经说过,用户体验不只是UED的事情,而是整个开发团队乃至整个公司需要参与的事情. 我们不能只是抱怨,我们去理解开发人员.同样,我们做出努力,让开发人员去理解我们. 我

PHP开发者常犯的10个MySQL错误

数据库是WEB大多数应用开发的基础.如果你是用PHP,那么大多数据库用的是MYSQL也是LAMP架构的重要部分. PHP看起来很简单,一个初学者也可以几个小时内就能开始写函数了.但是建立一个稳定.可靠的数据库确需要时间和经验.下面就是一些这样的经验,不仅仅是MYSQL,其他数据库也一样可以参考. 1.使用MyISAM而不是InnoDB MySQL有很多的数据库引擎,单一般也就用MyISAM和InnoDB. MyISAM是默认使用的.但是除非你是建立一个非常简单的数据库或者只是实验性的,那么到大多

PHP开发者常犯的10个MySQL错误更正剖析_php技巧

1.使用MyISAM而不是InnoDB 完全错误,反驳理由: 首先原文说MyISAM是默认使用的,而实际上到了MySQL 5.5.x,InnoDB已经成为了默认的表引擎. 另外,简单的使用InnoDB不是解决所有问题的方法,盲目的使用甚至会使应用性能下降10%乃至40%. 最佳方法还是针对具体业务具体处理,例如论坛中版块表,新闻分类表,各种码表等长时间不操作的表,还是要用性能优异的MyISAM引擎. 而需要用到事务处理的例如用户.账目.流水等严格要求数据完整性和时序性的,则需要用InnoDB引擎

Java程序员在写SQL程序时候常犯的10个错误

  Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准: 技能(任何人都能容易学会命令式编程) 模式(有些人用"模式-模式",举个例子,模式可以应用到任何地方,而且都可以归为某一类模式) 心境(首先,要写个好的面向对象程序是比命令式程序难的多,你得花费一些功夫) 但当Java程序员写SQL语句时,一切都不一样了.SQL是说明性语言而非面向对象或是命令式编程语言.在SQL中要写个查询语句是很简单的.但在Java里类似的语句却不

基础C语言编程时易犯错误有哪些_C 语言

C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下"灵活的余地",但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误.看着有错的程序,不知该如何改起,通过对C的学习,积累了一些C编程时常犯的错误,以供参考. 1.书写标识符时,忽略了大小写字母的区别. main() { int a=5; printf("%d",A); } 编译程序把a和A认为是两个不同的变量名,而显示出错信息.C认为大写

yield在WCF中的错误使用——99%的开发人员都有可能犯的错误[上篇]

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题.这里要说的是另一个问题:对于返回类型为IEnumerable<T>的方法来说,我们可以使用yield return的方式来输出返回集合的元素.但是如果我们不了解yield 关键字背后的实现机制,很有可能造成很大的问题. 这是一个WCF相关的问题,我想99%的人都有可能会犯这样的错误--即使你对yield了解得非常透彻.闲话少说,我们通过一个简单的实例来说明这个问