【问题标题】:Does Unmanaged C# code compile into IL and run on the CLR?非托管 C# 代码是否编译为 IL 并在 CLR 上运行?
【发布时间】:2012-09-12 13:47:27
【问题描述】:

在询问manually managing CLR memory的过程中,我意识到我知道的很少。

我知道,当您退出托管上下文时,CLR 会在堆栈上放置一个“cookie”,这样垃圾收集器就不会占用您的内存空间;但是,在我读过的所有内容中,假设您正在调用一些用 C 编写的库。

我想在托管上下文之外用 C# 编写应用程序的整个写入层,以在低级别管理数据。然后,我想从托管层访问该层。

在这种情况下,我的非托管 C# 代码会编译为 IL 并在 CLR 上运行吗?这是如何工作的?

【问题讨论】:

  • 您提到用 C# 编写非托管代码。我假设您的意思是这不同于调用非托管代码来自 C#。如果是这样,我想看一个例子来说明你的意思。
  • 根据 oleksii 的回答,我正在寻找的东西根本不存在。因此,我无法向您展示一个示例。

标签: c# clr unmanaged


【解决方案1】:

我认为这与您在问题中提到的同一个 C# 数据库项目有关。

技术上可以用 C/C++ 或任何其他语言实现整个写入层。 技术上可以在 C# 中包含其他所有内容。我目前正在开发一个应用程序,该应用程序将非托管代码用于一些高性能的低级内容,并将 C# 用于业务逻辑和上层管理。

但是,任务的复杂性不容小觑。典型的做法是设计一个双方都能理解的合约。合约将暴露给托管语言,托管语言将触发对本机应用程序的调用。如果您曾经尝试过从 C# 调用 C++ 方法,您就会明白……此外,对非托管代码的每次调用都会产生相当大的性能开销,这可能会扼杀低级性能的整个想法。

如果您真的对高性能关系数据库感兴趣,那么请使用单一的低级语言。

如果您想拥有一个简单但完整的数据库实现,只需使用 C#。除非您完全了解其复杂性,否则请勿混合使用这两种语言。请参阅 Raven DB - 一个基于文档的 NoSQL 数据库,完全用 C# 构建。

我的非托管 C# 代码会编译为 IL 并在 CLR 上运行吗?

不,不存在非托管 C# 之类的东西。 C# 代码将始终编译为 IL 代码并由 CLR 执行。这是托管代码调用非托管代码的情况。非托管代码可以用多种语言 C/C++/Assembly 等实现,但 CLR 不知道该代码中发生了什么。

从评论中更新。 有一个工具 (ngen.exe) 可以将 C# 直接编译为本机架构特定的代码。该工具旨在通过删除 JIT 编译阶段并将本机代码直接放入可执行映像或库中来提高托管应用程序的性能。然而,这段代码仍然由 CLR 主机“管理”——内存分配和收集、托管线程、应用程序域、异常处理、安全性和所有其他方面仍然由 CLR 控制。因此,即使 C# 在技术上可以编译为本机代码,该代码也不会作为独立的本机映像运行。

这是如何工作的?

托管代码互操作与非托管代码。有几种方法可以做到这一点:

  • 通过 .Net Interop 的代码。这相对较快,但在代码中看起来有点难看(而且很难维护/测试)(good article with C#/C/Assembly samples)
  • 一种慢得多的方法,但对其他语言更开放:Web 服务(SOAP、WS、REST 和公司)、排队(如 MSMQ、NServiceBus 等),以及(可能)进程间通信。因此,非托管进程位于一端,托管应用程序位于另一端。

【讨论】:

  • @oleksii- 您的评论有一个例外C# 代码将始终编译为 IL 代码。如果使用 Microsoft 的 .Net 实现,有一个名为 ngen.exe 的工具可以将 IL 代码预编译为本机代码,从而避免在第一次方法或函数时发生的即时、IL->本机代码编译的开销叫做。但是,这可能会适得其反,因为 ngen.exe 必须提前针对特定体系结构,并且 JIT 编译器可能会使用可用于实际运行代码的平台的优化。干杯!
  • @GerardSexton,对不起,我最初的评论是写给你的,而不是 oleksii
  • @sgorozco 感谢您的留言。我不知道 ngen!
  • @sgorozco 是的,没错,我忘了那个。我会更新我的答案。但另一方面代码仍然由 CLR 管理(根本没有发生 JIT 编译),例如内存管理和 GC 由 CLR 控制,异常处理通过标准 CLR 管道等。
【解决方案2】:

我知道这是一个 C# 问题,但如果您熟悉 C++,C++/CLI 可能是一个值得考虑的选项。

它允许您有选择地将部分 C++ 代码编译为托管或非托管上下文 - 但是请注意,与 CLR 类型交互的代码必须在托管上下文中运行。

我不知道在 C++ 代码中从托管上下文转换到非托管上下文以及反之亦然的运行时成本,但我认为它必须类似于通过 .net Interop 调用本机方法的成本正如@oleksii 已经指出的那样,C# 很昂贵。以我的经验,如果您需要经常与本机 C 或 C++ 库进行交互,这确实得到了回报 - 恕我直言,从 C++/CLI 项目中调用它们比在 C# 中编写所需的 .net Interop 接口要容易得多。

请参阅此question,了解有关如何完成的一些信息。

【讨论】:

    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 2013-10-28
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多