c# - C# 到 C++/CLI 转换的陷阱

标签 c# .net c++-cli

我被要求将一些 C# 代码转换为 C++/CLI。我的一位经理询问了两者之间转换概念的潜在陷阱。

我很清楚这两种语言都被编译为公共(public)界面语言,并通过相同的公共(public)语言运行时运行。但是,可以保证一段为 .NET Framework 4.5 编译并调用 File.Exists(someFile); 的 C# 代码吗?将以与为 .NET Framework 4.5 编译并调用 File::Exists(someFile) 的一段 C++/CLI 代码完全相同的方式编译为 CIL; ?

理论上答案是肯定的,因为这似乎就是 .NET 框架的构建目的。然而,有没有办法验证这一点呢?是否有技术原因导致它一定是/不可能是这样?

最佳答案

当您编写 C++/CLI 代码并且您熟悉 C# 但不了解 C++/CLI 时,肯定会遇到一些陷阱。我将避免将其变成一个列表问题,并列举所有这些问题,仅列出更常见的错误:

  • C++/CLI 要求您在语言语法中明确值类型和引用类型之间的差异。您必须在引用类型引用上使用帽子^。就像String^ foo;。但有时你不这样做,你故意省略它。如StreamReader 文件;。它启用了“堆栈语义”,即 C++ RAII 模式的模拟。或者换句话说,当 file 变量超出范围时,编译器将自动处理它。您可以通过 C# using 语句了解这一点。最大的陷阱是在不应该使用帽子的时候使用帽子,例如int^ x = 42;。编译器会毫无怨言地接受它,但最终会得到一个装箱 int,这在运行时效率极低。

  • C++/CLI 语言和工具集的开发于 2005 年停止,此后一直处于维护模式。因此,它没有获得 C# 在那个时间范围内获得的好处,Linq 无疑是最重要的补充。没有 lambda 表达式支持,没有匿名类型,没有扩展方法。您不会喜欢转换使用这些语法结构的 C# 代码。

  • 考虑将 C# 转换为 C++/CLI 的理由只有一个,那就是利用其对与非托管代码互操作的强大支持。无需争论 pinvoke。一个非常常见的错误是将所有内容编译为 MSIL,包括 native C++ 代码。效果太好了,C++/CLI 编译器能够将任何 C++ 编译为 IL,只要它是符合标准 C++03 的代码即可。但结果是低效,它肯定不会在运行时作为托管代码运行,并且会像正常情况一样进行抖动,但没有来自 native 代码生成器的好处。这样可以更好的优化代码。

  • 编译器的输出是纯 MSIL,与 C# 生成的类型完全相同。加上使用 C++ 的程序部分的 native 代码,生成混合模式程序集。这使得程序集对进程的位数具有依赖性。或者换句话说,您可能从 C# 项目中了解到的 AnyCPU 目标并不适用。这是您在 EXE 项目中需要注意的事情,您必须明确平台目标设置。 “x86”是确保您的程序在 64 位操作系统上运行时仍然可以运行的常见选择。如果您想在 64 位操作系统上将程序作为 64 位进程运行,那么您需要创建 C++/CLI 程序集的两个版本,并使用安装程序部署正确的版本。

您无需担心 File::Exists(somefile) 调用,在 MSIL 中只有一种方法可以调用该方法。 C++/CLI 编译器将生成与 C# 编译器完全相同的 IL。如果您确实担心它,请通过使用 ildasm.exe 等反编译器查看 IL 来建立信心

关于c# - C# 到 C++/CLI 转换的陷阱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17783305/

相关文章:

c# - 是否可以通过其他方法关闭 SQLite DB 连接?

java - 我可以像 C# 构造函数一样创建 Java 构造函数吗?

.net - 是否可以在 VC++/CLI 中重写 IEnumerable?

c++-cli - C++/CLI x64 WindowsForms 应用程序的入口点 (VS 2015)

c# - 枚举的字符串表示

javascript - Jquery 处理提交按钮的单击事件而不中断表单发布

c# - .NET 有什么好的分布式代理/服务模型吗?

.net - 如果在执行查询时没有 Complete() 我的 TransactionScope 会发生什么?

c# - 在子列表中传递带有过滤器/组的对象

c# - C++/CLI 性能与 native C++ 相比?