演習 - try-catch 例外処理を実装する

完了

try-catch パターンは、try ブロックとそれに続く 1 つ以上のcatch句で構成されます。 各 catch 句は、異なる例外の種類のハンドラーを指定します。

例外がスローされると、共通言語ランタイム (CLR) は、例外を処理できる catch 句を検索します。 現在実行中のメソッドに、スローされた例外の種類を処理できる catch 句が含まれていない場合、CLR は現在のメソッドを呼び出したメソッドを検索します。 検索は、適切な catch 句が見つかるまで呼び出し履歴を経由して続行されます。 例外を処理する catch 句が見つからない場合、CLR は未処理の例外メッセージをユーザーに表示し、プログラムの実行を停止します。

この演習では、基本的な try-catch パターンを実装します。

新しいコード プロジェクトを作成する

最初の手順では、このモジュールで使用するコード プロジェクトを作成します。

  1. Visual Studio Code の新しいインスタンスを開きます。

  2. [ ファイル ] メニューの [ フォルダーを開く] を選択します。

  3. [ フォルダーを開く] ダイアログで、Windows デスクトップ フォルダーに移動します。

  4. [ フォルダーを開く ] ダイアログで、[ 新しいフォルダー] を選択します。

  5. 新しいフォルダーに Exceptions101 という名前を付け、[フォルダーの選択] を 選択します

  6. [ ターミナル ] メニューの [ 新しいターミナル] を選択します。

    .NET CLI コマンドを使用して、新しいコンソール アプリを作成します。

  7. TERMINAL パネルのコマンド プロンプトで、次のコマンドを入力します。

    dotnet new console
    
  8. [ターミナル] パネルを閉じます。

単純な try-catch を実装する

  1. Visual Studio Code EXPLORER ビューを使用して、Program.cs ファイルを開きます。

  2. [表示] メニューの [ コマンド パレット] を選択します。

  3. コマンド プロンプトで「.net: g」と入力し、[.NET:ビルドとデバッグ用の資産を生成する] を選択してください。

  4. Program.cs ファイルの内容を次のコードに置き換えます。

    double float1 = 3000.0;
    double float2 = 0.0;
    int number1 = 3000;
    int number2 = 0;
    
    Console.WriteLine(float1 / float2);
    Console.WriteLine(number1 / number2);
    Console.WriteLine("Exit program");
    
  5. 時間を取ってコードを確認してください。

    アプリケーションでは、 doubleintの 2 つの数値変数型が使用されていることに注意してください。 このコードは、両方の数値型を使用して除算計算を実行します。

    正確な小数部の値が重要な場合、開発者は計算に double 型変数を使用します。

  6. [実行] メニューで、[デバッグの開始] を選択します。

    整数値を除算すると、 DivideByZeroException 例外が発生することに注意してください。

    double型の変数を使用する数式は、エラーを引き起こさずに完了できることに気付いたかもしれません。 double 型の変数を使った 0 除算計算は、無限大、負の無限大、または "数字ではありません" に等しい結果を返します。 これは、double型やint型ではなく、常にdecimal型変数を使用する必要があることを意味するわけではありません。 適切な方法は、適切な型の変数を使用し、例外処理を実装して、発生する可能性のあるエラーをキャッチすることです。

  7. [ デバッグ] ツール バーの [ 続行] を選択します。

    デバッグ ツール バーの [続行] ボタンを示すスクリーンショット。

  8. アプリケーションのメッセージ出力を調べるのに少し時間がかかります。

    ∞
    Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
       at Program.<Main>$(String[] args) in C:\Users\msuser\Desktop\Exceptions101\Program.cs:line 7
    

    ハンドルされない例外により、最初の Console.WriteLine() ステートメントが完了した後にアプリケーションがシャットダウンされたことに注意してください。

    既定では、Visual Studio Code では異なる色のテキストを使用して、デバッガーによって生成されたメッセージが表示されます。 これにより、開発者はアプリケーションの出力メッセージとデバッガー メッセージを区別できます。 アプリケーションの出力をよりクリーンに表示する場合は、別のコンソールを使用するように launch.json ファイルを構成できます。 たとえば、アプリケーション出力に TERMINAL パネルを使用するには、 consoleintegratedTerminal に設定します。 デバッガー メッセージは常に [デバッグ コンソール] パネルに表示されます。

  9. 次のように、 try ステートメントのコード ブロック内で 2 つの計算を囲みます。

    double float1 = 3000.0;
    double float2 = 0.0;
    int number1 = 3000;
    int number2 = 0;
    
    try
    {
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    
    Console.WriteLine("Exit program");
    
  10. try ブロックの閉じかっこの下にある赤い波線に注目してください。

    catch ステートメントを使用する場合、C# 構文にはfinally句または try 句が必要です。

  11. 次のように、catch コード ブロックの下にtryコード ブロックを構築します。

    try
    {
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    catch
    {
        Console.WriteLine("An exception has been caught");
    }
    
  12. Visual Studio Code の [ファイル] メニューで、[保存] を選択します。

  13. [実行] メニューで、[デバッグの開始] を選択します。

  14. アプリケーションによって生成された出力を調べるのに 1 分かかります。

    ∞
    An exception has been caught
    Exit program
    
  15. 例外は引き続き発生しますが、アプリケーションは終了する前に残りのコード行の実行を完了できることに注意してください。

    例外処理を使用すると、例外が発生したときにコードの実行を制御できます。 例外処理は、コードが安定していて、期待される結果を生成するのに役立ちます。

呼び出されたメソッドでスローされた例外をキャッチする

多くの場合、例外は、例外がスローされたレベルよりも下の呼び出し履歴のレベルでキャッチされます。

例外がスローされ、現在のメソッドが例外をキャッチしない場合、共通言語ランタイムはスタックをアンワインドし、例外を処理できる catch 句を含むメソッドを探します。 例外を処理できる最初の catch 句が実行されます。 呼び出し履歴のどこにも適切な catch 句が見つからない場合、共通言語ランタイムはプロセスを終了し、エラー メッセージをユーザーに表示します。

  1. Program.cs ファイル内のコードを次のコードに置き換えます。

    try
    {
        Process1();
    }
    catch
    {
        Console.WriteLine("An exception has occurred");
    }
    
    Console.WriteLine("Exit program");
    
    static void Process1()
    {
        WriteMessage();
    }
    
    static void WriteMessage()
    {
        double float1 = 3000.0;
        double float2 = 0.0;
        int number1 = 3000;
        int number2 = 0;
    
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    
  2. 更新されたコードを確認するには、少し時間がかかります。

    • 最上位レベルのステートメントには、try メソッドを呼び出すProcess1() コード ブロックが含まれます。
    • Process1() メソッドは、WriteMessage() メソッドを呼び出します。
    • WriteMessage() メソッドには、DivideByZeroException例外がスローされるコードが含まれています。

    例外は、 trycatch コード ブロックの上にある 2 つの呼び出し履歴レベルのメソッドで生成されることに注意してください。

    例外がスローされてからキャッチされるまでの呼び出し履歴レベルを示すスクリーンショット。

    最上位レベルのステートメントは、呼び出し履歴の Main という名前のメソッドとして表されます。

  3. Visual Studio Code の [ファイル] メニューで、[保存] を選択します。

  4. [実行] メニューで、[デバッグの開始] を選択します。

  5. アプリケーションによって生成された出力を調べるのに 1 分かかります。

    ∞
    An exception has occurred
    Exit program
    
  6. 呼び出し履歴で例外が 2 レベル上にスローされても、正常に処理されていることに注意してください。

まとめ

このユニットで覚えておく必要があるいくつかの重要な点を次に示します。

  • アプリケーション内の特定のコード行を try し、try コード ブロックのスコープ内で発生した例外を catch する try-catch パターンを実装します。
  • 同じレベルのコールスタックでスローされた例外をキャッチするには、catch 句を使用します。
  • 呼び出し履歴の高いレベルでスローされた例外をキャッチするには、catch 句を使います。