Они не эквивалентны.
Для ref int[] arr
атрибуты [In, Out]
по умолчанию будут применяться автоматически, но они по-прежнему не совпадают с [In, Out] int[] arr
.
ref int[] arr
- двойное косвенное обращение (ссылочный тип, передаваемый по ссылке). Используйте это, если нативная сторона определена примерно так: int32_t** arr
. Это позволяет заменить не только элементы, но и весь экземпляр массива.
С другой стороны, [In, Out] int[] arr
- это простая ссылка, передаваемая по значению. Используйте это, если нативная сторона также использует одиночное косвенное обращение, например. int32_t* arr
. Обычно в C #, если вы передаете массив по значению (который является ссылочным типом), вызываемый метод может заменить элементы, которые будут отражены со стороны вызывающей стороны. Однако маршалинг P / Invoke работает немного иначе :
По умолчанию ссылочные типы (классы, массивы, строки и интерфейсы), передаваемые по значению, маршалируются как In
параметры из соображений производительности. Вы не увидите изменений в этих типах, если не примените InAttribute
и OutAttribute
(или просто OutAttribute
) к параметру метода.
Таким образом, нативная сторона получает правильный указатель независимо от указания атрибута Out
. Здесь необходимо указать [Out]
для маршалера, чтобы он не пропустил сеанс обратного копирования в управляемую память.
Аналогично, in int length
будет передавать ссылку на целое число и не совпадает с [In] int length
, который передает параметр просто по значению. [In]
может быть опущено, так как в этом случае это стандартное поведение маршалинга.