C#面试题更新 2026-08-05

请解释在 .NET 平台中,如何使用 IL Emit 来实现代码的动态生成与执行?

编码实现技术原理C#.NET

考察说明

考查对 .NET 底层元数据和 IL 指令的了解,以及动态程序集构建流程的掌握。

回答思路

  1. 【回答框架 1】IL Emit 是 System.Reflection.Emit 命名空间提供的一组 API,允许在运行时动态创建程序集、模块、类型和方法。其核心目标是生成托管代码的元数据与中间语言指令,而非直接生成机器码。
  2. 【回答框架 2】典型流程为:先创建动态程序集(AssemblyBuilder)和模块(ModuleBuilder),再定义类型(TypeBuilder)与方法(MethodBuilder),通过 ILGenerator 的 Emit 方法发出 IL 指令,最后调用 CreateType 使类型可用,并用反射创建实例和调用方法。
  3. 【回答框架 3】实现动作分为几种:一是生成新类型和完整方法体;二是动态方法(DynamicMethod),无需程序集和类型即可生成轻量方法;三是修改现有方法的 IL,但只能整体替换,无法在运行时直接改写原方法体。
  4. 【回答框架 4】执行时,动态生成的类型或方法在首次调用时由 JIT 编译为机器码。相比反射调用,动态方法在预先生成委托(如 Func 或 Action)后,调用开销接近普通方法,比纯反射更快。
  5. 【回答框架 5】需确保生成的 IL 类型匹配、栈深度正确和分支目标有效,否则会在 JIT 阶段抛出 InvalidProgramException 或 BadImageFormatException。可用工具如 ILDasm 或 dnSpy 验证生成的 IL。
  6. 【关键点 1】核心是 System.Reflection.Emit 下的 AssemblyBuilder、TypeBuilder、MethodBuilder 和 ILGenerator。
  7. 【关键点 2】轻量场景优先用 DynamicMethod,无需完整程序集,性能接近原生调用。
  8. 【关键点 3】生成后必须先调用 CreateType(对于 TypeBuilder)让类型生效。
  9. 【关键点 4】使用 Emit 时需注意 IL 栈平衡和类型约束。
  10. 【关键点 5】动态代码的安全与版本依赖需提前评估,避免引入不稳定方案。
  11. 【易错点 1】不要认为 IL Emit 能直接生成可执行的机器码,它生成的是 IL,需 JIT 编译。
  12. 【易错点 2】不要混淆 DynamicMethod 与 MethodBuilder 的适用范围,前者适合简单方法,后者适合完整类型定义。
  13. 【易错点 3】生成环境需有 Reflection.Emit 权限,在部分 AOT 或受限环境下可能不可用。