经验丰富的 C++ 程序员在 C# 开发中最常见或最严重的错误

Posted

技术标签:

【中文标题】经验丰富的 C++ 程序员在 C# 开发中最常见或最严重的错误【英文标题】:Most common or vicious mistakes in C# development for experienced C++ programmers 【发布时间】:2010-03-11 12:25:15 【问题描述】:

当有经验的 C++ 程序员使用 C# 开发时,最常见或最严重的错误是什么?

【问题讨论】:

社区维基,也许吧? (PS - “主观和争论”的结束投票,我不同意。我认为这个问题不太可能导致争论!;) 【参考方案1】: 两者中structclass的区别 using 别名和typedef 之间的区别 什么时候收集我的物品?我该如何销毁它们现在int 有多大? (其实是用C#定义的) 我的链接器在哪里? (实际上,对于某些场景,Mono 确实有一个完整的 AOT 链接器)

【讨论】:

int 有多大。定义明确的语言和环境的乐趣:) 我觉得有义务指出 C++ 对其实现进行了定义,以便编译器可以使用性能最高的本机类型,而不是受到规范的限制。如果您需要,有可用的尺寸类型。 @Mark 在 C99 中有 stdint.h。这在标准 C++ 中还不是。 (它在 tr1 中,但未在 MSVC 2008 中实现)请参阅 stdint.h 上的 wiki 条目 @KitsuneYMG :是的,它在 C 标准中,而不是 C++ 标准中,这就是为什么它在 VS2008 中不受支持,即使在他们的 TR1 中也是如此。但是它是在 boost 中并且它只是标题,所以它不会让你的 exe 变得更大;)【参考方案2】:

我见过许多 C++ 程序员在 C# 中以 COM 风格编写代码,试图处理语言的不足之处。 C# 为您的枚举提供了大量类型安全的支持,并且通常有更好的 API,然后 P/Invoking 回到 C++。

我看到的另一件事引起大多数人的注意是 C# 泛型不是模板。

【讨论】:

【参考方案3】:

致电GC.Collect

【讨论】:

+1。我见过程序员担心他的对象会留在内存中的代码,他不断地调用它。【参考方案4】:
    一直使用结构来支持类。 一直使用 in、out 和 ref 参数(这是第 1 点的结果)。 使用 int 值作为错误条件而不是使用异常 使用 virtual 关键字而不是 override 关键字。 认为 char 是 8 位有符号值

【讨论】:

前三个听起来更像是 C 程序员会犯的错误......或者可能是非常糟糕的 C++ 程序员。 C++ 程序员,就像 C 程序员一样习惯于认为大多数时候使用值类型就可以了。 #3 在 C++ 和 C# 中同样错误;它看起来更像是 C 程序员使用这些语言中的任何一种都会做的事情。 Re #3:“返回代码被认为是有害的”?很抱歉,但如果您需要收集中间结果并需要继续进行,例外是不允许的。枚举返回码有它们的位置。使用 try catch 来控制“常规”流程并不是最好的主意。【参考方案5】:

认为“垃圾收集”=“我根本不必担心对象的生命周期”。例如,打开FileStream 却忘记关闭它。

或者:

    分配大量对象 将它们放入一个大的全局字典中(通常在“我知道,我会做一个缓存”之后) 想知道为什么应用程序的内存使用量总是上升而从不下降(“但它应该进行垃圾收集!”)

【讨论】:

FileStream 不会像 fstream 那样在其析构函数中关闭吗? @henle:你不知道什么时候会调用析构函数,所以最好手动调用dispose,或者使用语义。 好吧,在 C++ 中,你确信一旦变量超出范围,析构函数就会被调用,所以通常不需要显式地处理资源(这是 RAII 的重点) . 当 CLR 需要回收内存时,会调用 FileStream 终结器。如果有足够的可用内存,那么在程序退出之前FileStream 可能不会最终确定。 .NET 终结器与 C++ 析构函数不同。如果清理代码不重要,那么您可以将其留给垃圾收集时间(最终确定)。如果您确实需要确定性清理——比如关闭文件句柄——请致电IDisposable.Dispose【参考方案6】:

混淆“按引用传递”和“引用类型”:

void GetAnArray(int input, ref string[] output);

(与 C++ 比较:void getAnArray(int input, std::vector<std::string>& output);

【讨论】:

【参考方案7】: RAII 与 IDispose 值类型与引用类型(结构与类、装箱和拆箱等)

【讨论】:

【参考方案8】:

每次都编写完整的命名空间。

当您键入 std::thisboost::that 时,这在 C++ 中很好。当你到处重复 System.Windows.Forms.Whatever 时,在 C# 中就不那么好了。

【讨论】:

【参考方案9】:

顺便说一句,C# 编译器中有许多启发式方法可以帮助有经验的 C++ 程序员和新手 C# 程序员。例如,如果你说

int x[];

编译器会帮助指出 [] 是 C# 中类型的一部分,因此您可能的意思是

int[] x;

C# 还允许在类声明的末尾放置不必要的分号,这样有这种习惯的 C++ 程序员就不会被它所困扰。

【讨论】:

【参考方案10】:

忘记为每个类成员指定访问修饰符。

【讨论】:

@Judah Himango:我的意思是,在 C++ 中,您为不同的访问区域使用标签。我经常发生在方法之前忘记写public,因为之前的方法也是公开的。我看到这种情况一直发生在学习 C# 的 C++ 程序员身上。【参考方案11】:

尝试在strings 上实现const 的正确性。

【讨论】:

【参考方案12】:

我相信很多非 C++ 人也是如此,因为注册事件使对象保持活动状态而导致内存泄漏。

IDisposable 一开始就被磨碎了(如果我说实话,现在仍然如此),但从本机代码到托管代码时显然会有所不同,所以我不希望 C++ 开发人员真正犯规,他们就是不喜欢。

【讨论】:

【参考方案13】:

使用匈牙利表示法和其他 C++ 命名约定

private int m_iMyIntField;
class CWidget  ... 

【讨论】:

误用的匈牙利表示法并不是 C++ 特有的,它更像是 WIN32 和 MFC 库的产物。 你的意思是像 IMyInterface 或 MyException?

以上是关于经验丰富的 C++ 程序员在 C# 开发中最常见或最严重的错误的主要内容,如果未能解决你的问题,请参考以下文章

TIOBE 5月编程语言榜单出炉,C#最受开发者欢迎,C++将冲击Top 3

从 C# 应用程序调用 C++ 代码或移植它?

C#中构建多线程应用程序

三年的python开发经验,总结出这30个常见错误,避免重蹈覆辙!!!

如何在Visual Studio中选择C++和C#的编译器版本

如何将 opencv c++ 代码集成到使用 c# 以统一 3D 开发的移动应用程序中