在 ldloca 和调用之前,我是否需要 initobj/assign null 来输出参数?

Do I need to initobj/assign null to out arguments before ldloca and call?

正如我所见,C# 编译器和 Reflection.Emit 总是为值和引用类型变量发出 .locals init(即使它们稍后被无条件初始化)。所以它们可以作为输出参数传递:

    .maxstack 1
    .locals init (
        [0] object x)
    L_0000: ldloca.s x
    L_0002: call void Program::MethodWithOut(object&)
    L_0007: ret 

有没有在没有 init 的情况下使用 .locals 的情况,所以在发出 call/callvirt 之前我需要确保变量已初始化?

当您通过 ref 传递参数时,您需要在传递之前对它们进行初始化。 当您通过 out 传递参数时,它们必须在被调用的方法中进行初始化。

简单的答案是 init 总是 使代码可验证所必需的。来自ECMA-335的§III.1.8.1.1验证算法

Furthermore, verifiable methods shall have the localsinit bit set […]. If this bit is not set, then a CLI might throw a Verification exception at any point where a local variable is accessed, and where the assembly containing that method has not been granted SecurityPermission.SkipVerification.