何时有必要/适当使用InAttribute和OutAttribute进行COM Interop

Mic*_*eld 16 c# com-interop

我正在尝试遍历各种项目中分散的COM互操作定义的混乱,并将它们收集到一个已知良好的位置,整个开发团队可以从中受益.这项工作的一部分涉及清理多年来积累的定义.

其中一些是从其他源代码借来的,有些是从pinvoke.net逐字复制的,有些看起来是直接从SDK头文件中翻译过来的.我注意到的一件事是关于何时使用各种编组属性没有一致性(即使在pinvoke.net示例中,这也非常棒).部分问题是,我不认为这里的任何人(包括我自己)完全理解何时需要各种属性,或者他们实际做了什么.到目前为止,获得这些权利似乎是猜测和随机变化的结合,直到COMExceptions停止发生,但我更倾向于翻译是正确的,因为有人实际上看了他们并宣布他们如此.

所以,我开始[In][Out].我知道这两个属性在概念上是什么:它们告诉编组人员数据必须走向哪个方向.例如,我假设 marshaller不会打扰将[In]数据复制回调用者,或者知道[Out]可能需要在被调用者端释放数据,等等.我不知道的事情是:

  1. 什么时候需要使用这些属性?也就是说,什么时候默认的编组行为是错误的,这样属性才能使其正确?
  2. 什么时候使用这些属性是安全的?也就是说,指定什么应该是默认行为会改变marshaller的工作方式?
  3. 什么时候使用这些属性是危险的?我假设显式标记输出参数[In]是坏的,但是标记输入参数[In, Out]实际上会破坏任何东西?

因此,给定一个假设的COM接口方法,其IDL如下所示:

HRESULT Foo(
    [in] ULONG a,
    [out] ULONG * b
    [in, out] ULONG * c);
Run Code Online (Sandbox Code Playgroud)

我可能会将此翻译为以下任何一种:

void Foo(
  uint cb,
  out uint b,
  ref uint c);

void Foo(
  uint cb,
  [Out] out uint b,
  [In, Out] ref uint c);

void Foo(
  [In] uint cb,
  [Out] out uint b,
  [In, Out] ref uint c);
Run Code Online (Sandbox Code Playgroud)

这三者之间有什么功能差异吗?除了技术正确性之外,其中任何一个都被认为比其他人"更好"吗?

Cod*_*ray 16

不,在您自己的代码中应用任何这些属性并不是绝对必要的.它们都是可选的,并根据参数的类型自动应用于您的代码.

从本质上讲,它们具有以下C#关键字等价物:

  • [In]默认得到.
  • ref关键字得到你[In, Out].
  • out关键字得到你[Out].

在一个不错的表中的所有记录在这里.

当您想要更改这些隐含语义或更改封送器的默认行为时,您只需要使用它们.例如,您可以标记ref使用该[In]属性声明的参数,以抑制编组的"out"部分.

也就是说,我发现自己使用它们是因为它们是一种非常简单的方法,可以使代码自我记录.