Подтвердить что ты не робот

Могу ли я использовать SafeHandle вместо IntPtr?

Я искал интернет по всему миру, но не нашел хорошего объяснения.

Мой вопрос довольно прост.

У меня есть DLL, которая имеет функцию Initialize, а один из параметров - указатель, который получит дескриптор, который будет использоваться с последующими вызовами. Другим параметром является строка, которую я буду перечислять для полноты. Подпись, которую я использую, (в простой форме):

[DllImport(MyDll)]
static extern bool Initialize([In] string name, out IntPtr handle);

Подпись в самой DLL записывается как: Initialize(LPTSTR name, HANDLE handle) с комментарием "HANDLE: указатель на местоположение, которое получит дескриптор".

И последующие вызовы находятся в форме

[DllImport(MyDll)]
static extern bool DoSomething(IntPtr handle, uint randomParameter);

Я читал о SafeHandle, и мне было интересно, могу ли я использовать его для подстановки для моего дескриптора IntPtr. И если смогу, как мне это сделать? Расширение абстрактного класса SafeHandle не является проблемой, но могу ли я напрямую подставить мой IntPtr для SafeHandle (и использовать по умолчанию Marshalling) или мне нужно сделать что-то лишнее?

4b9b3361

Ответ 1

Вы можете найти более полный ответ о различии между SafeHandle и IntPtr здесь: IntPtr, SafeHandle и HandleRef - Разъяснение

Однако, чтобы суммировать, следует использовать IntPtr, где аргумент на самом деле является указателем размера машины - SafeHandle, где аргумент фактически является дескриптором Win32. Эти типы обычно не взаимозаменяемы; размер IntPtr будет меняться на разных архитектурах (32 бит на x86 и 64 бит на x64 и amd64). ПРИМЕЧАНИЕ. Под крышками я считаю, что SafeHandle также использует IntPtr).

Кроме того, в отличие от IntPtr, SafeHandle фактически выполняет удаление ресурсов, когда тип является собранным мусором. Это гарантирует, что системные ресурсы не будут утечки, когда ваша программа будет запущена (хотя вы должны Dispose() из SafeHandle экземпляров раньше, когда это возможно). Обратите внимание, что SafeHandle на самом деле абстрактно, потому что существует много разных типов ручек, для которых требуются разные подходы для правильной утилизации и обработки.

В вашем конкретном случае вам нужно посмотреть документацию для DLL, которую вы вызываете. Если это Win32 DLL, для него уже может быть тип SafeHandle. Если это сторонняя DLL, тогда вы можете свернуть собственную реализацию SafeHandle - считая, что помимо Initialize() существует некоторая версия Release() (или эквивалентная).

Некоторые дополнительные интересные лакомые кусочки о IntPtr vs SafeHandle можно найти по адресу:

Использовать SafeHandle для инкапсуляции собственных ресурсов

Ссылка на класс SafeHandle

SafeHandles и критическая финализация