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

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

【问题讨论】:

  • 社区维基,也许吧? (PS - “主观和争论”的结束投票,我不同意。我认为这个问题不太可能导致争论!;)

标签: c# c++


【解决方案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】:
    1. 一直使用结构来支持类
    2. 一直使用 in、out 和 ref 参数(这是第 1 点的结果)。
    3. 使用 int 值作为错误条件而不是使用异常
    4. 使用 virtual 关键字而不是 override 关键字。
    5. 认为 char 是 8 位有符号值

    【讨论】:

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

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

    或者:

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

    【讨论】:

    • 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?
                猜你喜欢
                • 2011-05-21
                • 2011-01-13
                • 1970-01-01
                • 2023-03-24
                • 1970-01-01
                • 2023-03-10
                • 1970-01-01
                • 1970-01-01
                • 2011-06-15
                相关资源
                最近更新 更多