你提到的“托管代码”与“与托管代码”似乎是对术语的重复或笔误。这里我会解释 托管代码非托管代码(通常是与托管代码相对的概念),以及它们的区别。

1. 托管代码(Managed Code)

托管代码 是由 .NET 运行时(如 CLR,即公共语言运行时)托管和管理的代码。也就是说,托管代码的执行是在 CLR 环境中进行的,CLR 提供了内存管理、异常处理、垃圾回收、安全性等功能。这意味着开发者无需自己管理内存分配和释放,CLR 会负责这些操作。

特点:

  • 内存管理:托管代码的内存管理是由垃圾回收器(GC,Garbage Collector)自动处理的。
  • 类型安全:CLR 会确保类型的安全性,例如防止类型转换错误、非法内存访问等。
  • 自动垃圾回收:CLR 会定期回收不再使用的内存空间,避免内存泄漏。
  • 安全性:CLR 会进行代码的安全检查,确保代码不会执行恶意操作。
  • 平台独立性:托管代码一般是通过 中间语言(IL,Intermediate Language) 编译的,这样可以通过不同平台上的 CLR 实现执行。

托管代码的一个例子就是 C# 中编写的代码,它会被编译成 中间语言(IL),然后在 .NET 环境中运行。

例如

1
2
3
4
5
6
7
8
9
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

上面的代码就是托管代码,它会被 C# 编译器编译为中间语言(IL),然后通过 CLR 执行。

2. 非托管代码(Unmanaged Code)

非托管代码 是指不由 CLR 或类似的运行时环境管理的代码。这类代码直接与操作系统交互,开发者必须手动管理内存、资源和安全性等问题。非托管代码通常是用 C++C 或其他低级语言编写的。

特点:

  • 手动内存管理:开发者需要自己负责分配和释放内存,容易出现内存泄漏问题。
  • 直接访问硬件:非托管代码能够直接操作硬件,进行系统级别的操作。
  • 无垃圾回收:没有像 CLR 那样的垃圾回收机制,必须手动释放资源。
  • 性能优势:由于没有运行时环境的管理,非托管代码通常比托管代码更加高效,尤其是在对性能要求极高的场景下。

非托管代码通常被编译为机器码并直接运行在操作系统上。

例如

1
2
3
4
5
6
#include <iostream>

int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}

上面的 C++ 代码是非托管代码,它被编译为机器代码,直接在操作系统中执行。

3. 托管代码与非托管代码的区别

特性 托管代码 非托管代码
执行环境 运行在 CLR(公共语言运行时)中 直接运行在操作系统上
内存管理 自动由 垃圾回收器(GC) 管理 需要开发者手动管理内存
类型安全 自动进行类型检查,防止类型错误 可能会发生类型错误,必须手动管理
安全性 CLR 进行安全检查,防止恶意代码执行 代码可能没有安全性保障,易受攻击
性能 性能较低,因为有垃圾回收等运行时开销 性能较高,因为没有运行时环境的开销
示例语言 C#、VB.NET、F# 等 C、C++ 等
可移植性 通过中间语言(IL)可以跨平台运行 必须针对每个平台进行编译

4. 托管代码与非托管代码的交互

虽然托管代码和非托管代码有很多差异,但在实际应用中,它们经常需要互相交互,特别是在需要访问系统底层或与已有的非托管代码库集成时。通常有几种方式来实现托管代码与非托管代码的交互:

  • P/Invoke(平台调用):托管代码可以通过 P/Invoke 调用非托管的 API(例如 Windows API)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    using System;
    using System.Runtime.InteropServices;

    class Program
    {
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetConsoleWindow();

    static void Main()
    {
    IntPtr hwnd = GetConsoleWindow();
    Console.WriteLine(hwnd);
    }
    }

    以上是通过 P/Invoke 调用 Windows 的非托管函数 GetConsoleWindow

  • C++/CLI(C++ 和托管代码混合):C++/CLI 是一种可以同时操作托管代码和非托管代码的语言,可以方便地在同一项目中混合使用 C++(非托管代码)和 C#(托管代码)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #using <System.dll>
    using namespace System;

    public ref class ManagedClass {
    public:
    void PrintMessage() {
    Console::WriteLine("Hello from C++/CLI!");
    }
    };
  • COM(组件对象模型):通过 COM 机制,非托管代码可以通过 COM 接口与托管代码进行交互。

5. 总结

  • 托管代码 是由 .NET 运行时管理的代码,它具有内存管理、安全性和平台独立性的优势。常见的托管语言包括 C# 和 VB.NET。
  • 非托管代码 是直接运行在操作系统上的代码,需要开发者手动管理内存和资源,常见的非托管语言包括 C 和 C++。
  • 在很多情况下,托管代码和非托管代码是需要协同工作的,Unity 中通常使用托管代码(如 C#),但在需要性能或底层系统调用时,也可以使用非托管代码(如 C++)。