Когда необходимо / целесообразно использовать InAttribute и OutAttribute для COM-взаимодействия - PullRequest
15 голосов
/ 21 декабря 2011

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

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

Итак, я начинаю с [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);

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

1 Ответ

15 голосов
/ 21 декабря 2011

Нет, нет необходимости применять какие-либо из этих атрибутов в вашем собственном коде.Все они являются необязательными и автоматически применяются к вашему коду в зависимости от типа параметра.

По сути, они имеют следующие эквиваленты ключевых слов C #:

  • Вы получаете [In]по умолчанию.
  • Ключевое слово ref возвращает вас [In, Out].
  • Ключевое слово out возвращает вас [Out].

Все задокументировано вхороший стол здесь .

Вам нужно использовать их только тогда, когда вы хотите изменить эту подразумеваемую семантику или изменить поведение маршалера по умолчанию.Например, вы можете пометить параметр, объявленный ref атрибутом [In], только для того, чтобы подавить часть «маршалинга».

Тем не менее, я использую их, потому что они очень просты.способ сделать код самодокументированным.

...