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

时间:2011-12-21 16:49:43

标签: c# com-interop

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

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

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

  1. 什么时候必要才能使用这些属性?也就是说,什么时候默认的编组行为是错误的,这样属性才能使其正确?
  2. 什么时候安全才能使用这些属性?也就是说,指定应该已经存在的默认行为会改变编组程序的工作方式吗?
  3. 什么时候危险才能使用这些属性?我假设显式标记输出参数[In]是坏的,但是标记输入参数[In, Out]实际上会破坏什么?
  4. 所以,给定一个假设的COM接口方法,其IDL如下所示:

    HRESULT Foo(
        [in] ULONG a,
        [out] ULONG * b
        [in, out] ULONG * c);
    

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

    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);
    

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

1 个答案:

答案 0 :(得分:15)

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

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

  • 默认情况下,您获得[In]
  • ref关键字为您提供[In, Out]
  • out关键字为您提供[Out]

所有记录在一个漂亮的表here中。

只有在想要更改隐含语义或更改封送程序的默认行为时,才需要使用它们。例如,您可以使用ref属性标记声明为[In]的参数,以禁止编组的“out”部分。

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