例外のスロー
実行するようにデザインされている処理をメンバーが正しく実行できなかった場合、例外がスローされます。 これを実行エラーと言います。 たとえば、Connect メソッドが、指定されたリモート エンド ポイントに接続できなかった場合は実行エラーであり、例外がスローされます。
以下のガイドラインに従うと、適切に例外をスローできます。
エラー コードは返さないでください。 例外は、フレームワークでエラーを報告するための主要な手段です。
「例外のデザインのガイドライン」では、例外を使用することから得られるさまざまな利点について説明しています。
例外をスローして実行エラーを報告してください。 実行するようデザインされている処理をメンバーが正しく実行できなかった場合は実行エラーと見なし、例外をスローする必要があります。
実行の継続が危険な状況にコードが遭遇した場合は、例外をスローする代わりに System.Environment.FailFast(System.String) (.NET Framework Version 2.0 の機能) を呼び出してプロセスを終了することを検討してください。
通常の制御フローでは、できれば例外を使用しないでください。 システム エラーや競合状態が発生する可能性がある操作を除き、フレームワークのデザイン時には、例外をスローしないコードをユーザーが記述できるように API をデザインする必要があります。 たとえば、メンバーを呼び出す前に状態をチェックできるようにすると、例外をスローしないコードをユーザーが記述できるようになります。
次のコード例は、メッセージ文字列が null (Visual Basic では Nothing) の場合に例外がスローされないようにテストする方法を示しています。
Public Class Doer
' Method that can potential throw exceptions often.
Public Shared Sub ProcessMessage(ByVal message As String)
If (message = Nothing) Then
Throw New ArgumentNullException("message")
End If
End Sub
' Other methods...
End Class
Public Class Tester
Public Shared Sub TesterDoer(ByVal messages As ICollection(Of String))
For Each message As String In messages
' Test to ensure that the call
' won't cause the exception.
If (Not (message) Is Nothing) Then
Doer.ProcessMessage(message)
End If
Next
End Sub
End Class
public class Doer
{
// Method that can potential throw exceptions often.
public static void ProcessMessage(string message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
}
// Other methods...
}
public class Tester
{
public static void TesterDoer(ICollection<string> messages)
{
foreach (string message in messages)
{
// Test to ensure that the call
// won't cause the exception.
if (message != null)
{
Doer.ProcessMessage(message);
}
}
}
}
public ref class Doer
{
public:
// Method that can potential throw exceptions often.
static void ProcessMessage(String^ message)
{
if (message == nullptr)
{
throw gcnew ArgumentNullException("message");
}
}
// Other methods...
};
public ref class Tester
{
public:
static void TesterDoer(ICollection<String^>^ messages)
{
for each (String^ message in messages)
{
// Test to ensure that the call
// won't cause the exception.
if (message != nullptr)
{
Doer::ProcessMessage(message);
}
}
}
};
スローされる例外の数を削減できるデザイン パターンの詳細については、「例外とパフォーマンス」を参照してください。
例外をスローすることによるパフォーマンスへの影響を考慮してください。
システム エラーではなく、メンバー コントラクトの違反が原因で、パブリックに呼び出し可能なメンバーによってスローされる例外をすべて記録し、それらをコントラクトの一部として扱ってください。 コントラクトに含まれる例外は、バージョン間で変更しないでください。
オプションによって例外をスローしたりしなかったりするようなパブリック メンバーを使用しないでください。
たとえば、次のようなメンバーは定義しないでください。
Private Function ParseUri(ByVal uriValue As String, ByVal throwOnError As Boolean) As Uri
Uri ParseUri(string uriValue, bool throwOnError)
Uri^ ParseUri(String^ uriValue, bool throwOnError)
戻り値または out パラメーターとして例外を返すパブリック メンバーを使用しないでください。
このガイドラインの対象は、パブリックに参照可能なメンバーです。 プライベートなヘルパー メソッドを使用して例外を構築し、初期化することは許容されます。
例外ビルダー メソッドを使用することを検討してください。 同じ例外を異なる場所からスローすることはよくあります。 コードが長くなることを避けるには、例外を作成し、そのプロパティを初期化するヘルパー メソッドを使用します。
ヘルパー メソッドからは例外をスローしないでください。例外をスローすると、例外を発生させた呼び出し履歴がスタック トレースに正確に反映されません。
例外フィルター ブロックから例外をスローしないでください。 例外フィルターで例外が発生すると、その例外は共通言語ランタイムでキャッチされ、フィルターから false が返されます。 この動作は、フィルターが実行し、false を明示的に返す動作と区別できないため、デバッグが困難です。
C# などの一部の言語は、例外フィルターをサポートしません。
finally ブロックから例外を明示的にスローするのは避けてください。 例外をスローするメソッドを呼び出した結果、暗黙にスローされる例外は許容されます。
Portions Copyright 2005 Microsoft Corporation. All rights reserved.
Portions Copyright Addison-Wesley Corporation. All rights reserved.
設計ガイドラインの詳細についてを参照してください、「フレームワークの設計ガイドライン。規則、慣用句、および再利用可能なパターン。ネット ライブラリ」本クシシュトフ Cwalina、ブラッド エイブラムス、アスキー、2005 年発表しました。