El objetivo de ambas estructuras es evitar que el recolector de basura libere un recurso e invalidar el identificador antes de que la llamada P/Invoke haya finalizado. La documentación que vinculó indica que estos son tipos especiales reconocidos por el contador de interoperabilidad.
Lo que deduzco de la documentación es que HandleRef
es esencialmente un caso especial de la estructura más general GCHandle
.
La estructura HandleRef
está específicamente diseñada para envolver controladores en recursos no administrados que se utilizan con el código P/Invoke. Por ejemplo, identificadores de ventana (HWND
) o contextos de dispositivo (HDC
). Tiene una propiedad Handle
que devuelve un valor de tipo IntPtr
, que es un valor entero del tamaño de un puntero en la arquitectura del sistema subyacente. Puede usar esto para rápidamente & obtener fácilmente el mango que envuelve.
Considerando que la estructura GCHandle
permite especificar el tipo de mango que se envuelve usando uno de los miembros de la GCHandleType
enumeración, la estructura HandleRef
fue diseñado específicamente para envolver los mangos a los recursos no administrados. Probablemente usaría la estructura GCHandle
cuando trabaje directamente con la memoria no administrada, en lugar de los identificadores especiales que la API de Win32 trata como cuadros negros.
No es necesario usar ninguno de los dos. Uno simplemente puede llamar al GC.KeepAlive
para evitar que el recolector de basura libere el recurso de forma prematura.
E incluso eso probablemente no sea necesario. He estado escribiendo el código P/Invoke durante años, y he descubierto que, cuando está escrito correctamente, no hay necesidad de ninguna de estas estructuras. Si un objeto de la clase obtiene basura recolectada mientras la llamada API se encuentra en el medio de la ejecución, entonces eso es un error en su aplicación. De hecho, quiero para ser notificado de la falla a través de una excepción, no ocultarlo.
Gracias por responder –
"He encontrado que cuando está escrito correctamente, no hay necesidad de ninguna de estas estructuras." ¿Qué sucede si no está preocupado por evitar que el objeto se recopile porque sabe que el código administrado seguirá haciendo referencia a él, pero simplemente desea que el código no administrado acepte/mantenga/devuelva referencias administradas por algún motivo? Ejemplo de caso de uso: stackoverflow .com/questions/32105089 –