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.
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.