Смысл обеих этих структур состоит в том, чтобы не дать сборщику мусора освободить ресурс и сделать недействительным дескриптор до завершения вызова P / Invoke. Связанная с вами документация указывает, что это специальные типы, распознаваемые маршаллером взаимодействия.
Из документации я понял, что HandleRef
по сути является частным случаем более общей структуры GCHandle
.
Структура HandleRef
специально предназначена для переноса дескрипторов на неуправляемые ресурсы, которые используются с кодом P / Invoke. Например, дескрипторы окон (HWND
) или контексты устройства (HDC
). Он имеет свойство Handle
, которое возвращает значение типа IntPtr
, которое является целочисленным значением размера указателя на архитектуру базовой системы. Вы можете использовать это, чтобы быстро и легко получить ручку, которую оборачивает.
Принимая во внимание, что структура GCHandle
позволяет указать тип дескриптора, который она переносит, используя один из элементов перечисления GCHandleType
, структура HandleRef
была специально разработана для переноса дескрипторов на неуправляемые ресурсы. Вы, вероятно, будете использовать структуру GCHandle
, когда имеете дело непосредственно с неуправляемой памятью, а не со специальными дескрипторами, которые Win32 API рассматривает как черные ящики.
Нет необходимости использовать либо. Можно просто позвонить GC.KeepAlive
, чтобы не дать сборщику мусора преждевременно освободить ресурс.
И даже это, вероятно, не нужно. Я годами писал код P / Invoke и обнаружил, что когда он написан правильно, нет необходимости ни в одной из этих структур. Если объект класса получает мусор во время выполнения вызова API, это ошибка в вашем приложении. Я на самом деле хочу, чтобы уведомлялся о сбое через исключение, а не скрывал его.