私は最近、Win32 API との相互運用に関連する多くのコードを作成しており、Windows API 関数の呼び出しによって発生するネイティブ (アンマネージ) エラーを処理する最善の方法は何かを考え始めています。
現在、ネイティブ関数の呼び出しは次のようになっています。
// NativeFunction returns true when successful and false when an error
// occurred. When an error occurs, the MSDN docs usually tell you that the
// error code can be discovered by calling GetLastError (as long as the
// SetLastError flag has been set in the DllImport attribute).
// Marshal.GetLastWin32Error is the equivalent managed function, it seems.
if (!WinApi.NativeFunction(param1, param2, param3))
throw new Win32Exception();
例外を発生させる行は、次のように同等に書き直すことができます。
throw new Win32Exception(Marshal.GetLastWin32Error());
Message
これで、設定された Win32 エラー コードと、(通常は) 人間が判読できるエラーの説明をException オブジェクトのプロパティとして適切に含む例外がスローされるという点で、これは問題ありません。ただし、これらの例外のすべてではないにしても、少なくとも一部を変更/ラップして、もう少しコンテキスト指向のエラー メッセージ、つまり、ネイティブ コードがどのような状況でもより意味のあるエラー メッセージが表示されるようにすることをお勧めします。使用されています。これにはいくつかの代替案を検討しました。
のコンストラクタでカスタム エラー メッセージを指定する
Win32Exception
。throw new Win32Exception(Marshal.GetLastWin32Error(), "My custom error message.");
を別の Exception オブジェクトにラップして
Win32Exception
、元のエラー コードとメッセージの両方が保持されるようにします (Win32Exception
は現在InnerException
、親例外の です)。throw new Exception("My custom error message.", Win32Exception(Marshal.GetLastWin32Error()));
Win32Exception
別のものをラッパー例外として使用することを除いて、2 と同じです。2 と同じ
Exception
ですが、ラッパー例外として から派生したカスタム クラスを使用します。適切な場合に親として BCL (Base Class Library) 例外を使用することを除いて、2 と同じです。
InnerException
この場合、 をに設定することが適切かどうかWin32Exception
はわかりません (おそらく、低レベルのラッパーの場合ですが、Win32 相互運用が舞台裏で行われていることを明らかにしない高レベル/抽象化されたインターフェイスではありませんか?)
基本的に私が知りたいのは、.NET で Win32 エラーを処理する際に推奨される方法は何ですか? さまざまな方法でオープンソース コードで行われているのを見てきましたが、設計ガイドラインがあるかどうかに興味がありました。そうでない場合は、ここであなたの個人的な好みに興味があります. (おそらく、上記の方法のどれも使用していませんか?)