16

たとえば、古い.NET Framework 2.0ソースコード(Windowsフォーム、Visual Studio 2005-Whidbey)では、 GetClientRect関数はHandleRefを使用して定義されていました

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

新しいWindowsAPIコードパック(Microsoft、2009/2010から)では、同じ関数がIntPtrを使用して定義されています。

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

実際、 HandleRefはWindows APIコードパックのソースファイルでは使用されていませんが、古い.NETFrameworkソースファイルのネイティブメソッドの署名では頻繁に使用されていました。

4

3 に答える 3

10

少し怪しいです。ハンドル値がSafeHandle派生オブジェクトに格納されている場合、HandleRefは必要ありません。コードパックが宣言しているZeroInvalidHandleと、SafeWindowHandleのような派生コードがいくつかあります。

ただし、実際にはこれらのSafeHandleクラスをどこでも使用していません。本当に必要かどうかはわかりませんが、VistaおよびWin7の拡張機能の多くは実際にはCOMインターフェイスです。従来のハンドルベースのCAPIではありません。それらは参照カウントを通じて存続しているため、この種のガベージコレクターの事故の影響を受けません。

個人的に私はこれについて心配することはありません。API呼び出しの実行に収集されたクラスオブジェクトを取得することはバグです。API呼び出しが完了してから1マイクロ秒に同じように簡単に発生する可能性があります。それでもバグであり、API呼び出しを失敗させるものではありません。実際に失敗しないようにしたいのかどうかはわかりませんが、コードにバグが発生した場合は例外を使用したいと思います。Microsoftはこれから身を守る必要があり、例外の責任を負いたくないのです。そうです。

于 2010-12-02T16:04:30.383 に答える
5

私の推測では、新しいコードサンプルはIntPtr、理解しやすいという理由だけで使用しています。

.NET Frameworkにあるさまざまなクラスの関数シグネチャをReflectorでざっと見るNativeMethodsと、実際の使用法が2つにかなりよく分かれていることがわかります。

これは、オブジェクトが時期尚早にガベージコレクションされるのを防ぐ必要があるかどうかに基づいていると思います(これは、を使用する主な利点HandleRefです)。また、HandleRef渡すハンドルが管理対象オブジェクトでない限り、使用は不要であることに注意してください。管理されていないオブジェクトはガベージコレクションされません。

于 2010-12-02T13:26:12.640 に答える
3

IntPtrは、ポインタをラップする単なる構造体です。HandleRefに関しては、MSDN、「HandleRefでハンドルをラップすると、プラットフォームの呼び出し呼び出しが完了するまで、管理対象オブジェクトがガベージコレクションされないことが保証されます」と述べています。P / Invokeの呼び出し後に何もしなかった場合、GCがP/Invoke中にハンドルをファイナライズできる可能性があります。したがって、HandleRefはより安全に見えます。

于 2010-12-02T13:17:12.567 に答える