一. 方向属性
平台调用和 COM 互操作都使用 Interop 封送处理在调用方和被调用方之间准确地移动方法参数,并且如果需要,也可以将数据从被调用方移回调用方。正如下面的插图所示,除涉及回调函数时以外,平台调用方法调用从托管代码流向非托管代码,而绝不会以相反方向流动。虽然平台调用的调用只能从托管代码流向非托管代码,但是数据仍然可以作为 In 或 Out 参数在两个方向流动。COM 互操作方法调用可以在任一个方向流动。
每个方法参数都可以与 InAttribute 属性和 OutAttribute 属性的设置分别或同时关联。可以在设计时应用方向属性以修改托管和非托管内存之间的运行时封送处理。
默认情况下,如果忽略来自方法参数的方向属性,则封送拆收器将根据参数的类型(值或引用)及其修饰符(如果有的话)确定方向流。例如,始终假定 StringBuilder 类为 In/Out。
[InAttribute] 指示应将数据从调用方封送到被调用方,而不返回到调用方,是可选项。
[OutAttribute] 指示数据从被调用方返回到调用方。
[InAttribute,OutAttribute] 仅当同时应用这两个属性时,调用方才能看到被调用方对这些类型所做的更改。
下表列出了 C# 所提供的与方向有关的关键字并显示等效的 IDL 接口属
C# |
IDL 属性 |
无等效项。 |
[in] |
ref |
[in/out] |
out |
[out] |
ref 和 out 参数修饰符导致方法参数通过引用而不是通过值进行封送。通过值传递的方法参数被作为堆栈上的值封送到非托管代码;通过引用传递的参数被作为堆栈上的指针封送。下面的插图显示具有参数修饰符的值类型和引用类型的默认封送处理行为。
将方法参数封送到非托管代码的默认封送处理
默认情况下,通过值传递的引用类型(类、数组、字符串和接口)出于性能原因而作为 In 参数封送。只有将 InAttribute 和 OutAttribute(或仅将 OutAttribute)应用于方法参数才能看见对这些类型所做的更改。StringBuilder 类(它是本规则的一个例外)被作为 In/Out 参数封送。