Когда необходимо/уместно использовать InAttribute и OutAttribute для COM Interop

Я пытаюсь разобраться в беспорядке определений COM interop, которые мы разбросали по разным проектам, и собрать их в одно, известное хорошее место, из которого вся команда разработчиков сможет извлечь пользу. Часть этих усилий включает в себя очистку определений, которые накапливались годами.

Некоторые из них заимствованы из других исходных текстов, некоторые были дословно скопированы с сайта pinvoke.net, а некоторые выглядят как прямой перевод из заголовков SDK. Я заметил одну вещь: нет последовательности в том, когда использовать различные атрибуты маршалинга (даже в примерах с pinvoke.net это довольно противоречиво). Отчасти проблема в том, что я не думаю, что кто-то здесь (включая меня) полностью понимает, когда различные атрибуты нужны или нет, или что они на самом деле делают. До сих пор, чтобы сделать их правильными, кажется, что это комбинация догадок и случайных изменений, пока COMExceptions не перестанут происходить, но я бы предпочел, чтобы переводы были правильными, потому что кто-то действительно посмотрел на них и объявил их такими.

Итак, я начинаю с [In] и [Out]. Я знаю, что эти два атрибута делают концептуально: они сообщают маршаллеру, в каком направлении должны идти данные. Я предполагаю, что маршаллер, например, не будет беспокоиться о копировании [In] данных обратно вызывающей стороне, или знает, что [Out] данные могут быть освобождены на стороне вызывающей стороны, и т.д. Я не знаю вот чего:

  1. Когда необходимо использовать эти атрибуты? То есть, когда поведение маршалинга по умолчанию неверно настолько, что атрибуты делают его правильным?
  2. Когда безопасно использовать эти атрибуты? То есть, изменит ли указание того, что уже должно быть поведением по умолчанию, работу маршаллера?
  3. Когда опасно использовать эти атрибуты? Я предполагаю, что явное обозначение выходного параметра [In] - это плохо, но разве обозначение входного параметра [In, Out] действительно может что-то сломать?

Итак, учитывая гипотетический метод 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);

Есть ли функциональная разница между этими тремя? Считается ли какой-либо из них "лучше" других по причинам, не связанным с технической корректностью?

16
задан Michael Edenfield 21 December 2011 в 16:49
поделиться