Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better/safer to use: HandleRef or IntPtr (newer source code from Microsoft no longer uses HandleRef)

For example, in the old .NET Framework 2.0 Source Code (Windows Forms, Visual Studio 2005 - Whidbey), the GetClientRect function was defined using HandleRef:

    [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)]
    public static extern bool GetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); 

In the new Windows API Code Pack (from Microsoft, 2009/2010) the same function is defined using IntPtr:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GetClientRect(IntPtr hwnd, ref CoreNativeMethods.RECT rect);

Actually HandleRef is not used in any of the Windows API Code Pack source files, while it was heavily used in the native methods signatures in the old .NET Framework source files.

like image 344
Alex Vang Avatar asked Dec 02 '10 13:12

Alex Vang


3 Answers

It's a bit fishy. HandleRef is not needed when handle values are stored in a SafeHandle derived object. Which the code pack declares, ZeroInvalidHandle, with several derived ones from it like SafeWindowHandle.

However, it doesn't actually use any of these SafeHandle classes anywhere. Not so sure if it really has to, a lot of the Vista and Win7 extensions are actually COM interfaces. Not the traditional handle based C API. They are kept alive through reference counts and are thus not subject to this kind of garbage collector mishap.

Personally I just never worry about this. Getting a class object collected while the API call is executing is a bug. It can happen just as easily a microsecond after the API call completed. Still a bug, just not one that makes the API call fail. Not so sure I'd actually want it to not fail, I'd much prefer an exception when I got a bug in my code. Microsoft needs to protect itself from this, they don't want to get the blame for the exception. I do.

like image 89
Hans Passant Avatar answered Nov 07 '22 01:11

Hans Passant


My guess is that the newer code samples use IntPtr merely because it's simpler to understand.

A quick glance through Reflector at the function signatures in the various NativeMethods classes found in the .NET Framework shows that the actual usage is pretty well split between the two.

I assume this is based on whether or not there is a need to prevent the object from being garbage collected prematurely (which is the primary advantage to using HandleRef). Also keep in mind that using HandleRef is unnecessary unless the handle that you're passing is to a managed object. Unmanaged objects will not get garbage collected.

like image 44
Cody Gray Avatar answered Nov 07 '22 01:11

Cody Gray


IntPtr is just structure that wraps pointer. As for HandleRef MSDN says "Wrapping a handle with HandleRef guarantees that the managed object is not garbage collected until the platform invoke call completes." There is a chance that GC can finalize handle during P/Invoke if you don't do anything with it after P/Invoke call. So HandleRef looks more safe.

like image 3
DReJ Avatar answered Nov 07 '22 02:11

DReJ