例外処理 (C# プログラミング ガイド)

C# では、例外による影響を受けることがあるコードを分割するために try ブロックを使用します。 その結果発生する例外を処理するためには、これに関連付けられた catch ブロックを使用します。 また、finally ブロックには、try ブロックで例外がスローされたかどうかに関係なく実行されるコード (try ブロックで割り当てたリリースの解放など) が置かれます。 try ブロックには、関連付けられた catch ブロックと finally ブロックの少なくとも 1 つ、またはその両方が必要です。

次の例では、try-catch ステートメント、try-finally ステートメント、および try-catch-finally ステートメントについて示します。

try
{
    // Code to try goes here.
}
catch (SomeSpecificException ex)
{
    // Code to handle the exception goes here. 
    // Only catch exceptions that you know how to handle. 
    // Never catch base class System.Exception without 
    // rethrowing it at the end of the catch block.
}
try
{
    // Code to try goes here.
}
finally
{
    // Code to execute after the try block goes here.
}
try
{
    // Code to try goes here.
}
catch (SomeSpecificException ex)
{
    // Code to handle the exception goes here.
}
finally
{
    // Code to execute after the try (and possibly catch) blocks  
    // goes here.
}

catch ブロックも finally ブロックも存在しない try ブロックは、コンパイラ エラーになります。

catch ブロック

catch ブロックでは、キャッチする例外の種類を指定できます。 種類の指定は、例外フィルターと呼ばれます。 例外の種類は、Exception から派生する必要があります。 通常、例外フィルターとして Exception は指定しません。ただし、try ブロックでスローされる例外の処理方法が判明している場合、または catch ブロックの末尾に throw ステートメントを挿入している場合を除きます。

異なる例外フィルターを持つ複数の catch ブロックを使用できます。 例外がスローされるたびに、コード内の catch ブロックが上から下に評価されますが、実行される catch ブロックは 1 つだけです。 実行されるのは、スローされた例外の種類または基本クラスを正確に指定している最初の catch ブロックです。 一致する例外フィルターを指定する catch ブロックがない場合は、フィルターを持たない catch ブロックが選択されます (そのようなブロックがステートメント内に存在する場合)。 最も限定的な (つまり、最派生の) 例外の種類を持つ catch ブロックを最初に配置することが重要です。

次の条件に当てはまる場合は、例外をキャッチする必要があります。

  • 例外がスローされた原因を明確に把握しており、FileNotFoundException オブジェクトをキャッチしたときにユーザーに新しいファイル名の入力を求めるなど、特定の回復措置を実装できる場合。

  • より限定的な新しい例外を生成し、スローできる場合。

    int GetInt(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch(System.IndexOutOfRangeException e)
        {
            throw new System.ArgumentOutOfRangeException(
                "Parameter index is out of range.");
        }
    }
    
  • 例外を部分的に処理してから、他の処理に例外を渡すことがあります。 次の例では、例外を再スローする前にエラー ログにエントリを追加するために catch ブロックが使用されています。

    try
    {
        // Try to access a resource.
    }
    catch (System.UnauthorizedAccessException e)
    {
        // Call a custom error logging procedure.
        LogError(e);
        // Re-throw the error. 
        throw;     
    }
    

finally ブロック

finally ブロックでは、try ブロックで実行されるアクションをクリーンアップできます。 finally ブロックが存在する場合、このブロックは、try ブロックと、一致した catch ブロックの後で最後に実行されます。 finally ブロックは、例外がスローされたかどうか、または例外の種類に一致する catch ブロックが見つかったかどうかとは無関係に常に実行されます。

finally ブロックを使用すると、ガベージ コレクターが実行時にオブジェクトを終了するのを待たずに、ファイル ストリーム、データベース接続、グラフィックス ハンドルなどのリソースを解放できます。 詳細については、「using ステートメント (C# リファレンス)」を参照してください。

次の例では、finally ブロックを使用して、try ブロックで開かれたファイルを閉じます。 ファイルを閉じる前に、ファイル ハンドルの状態がチェックされることに注意してください。 try ブロックでファイルを開くことができない場合でも、ファイル ハンドルの値は null のままであるため、finally ブロックでファイルを閉じようとすることはありません。 また、try ブロックで正常にファイルが開かれている場合は、finally ブロックでファイルが閉じられます。

System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");
try
{
    file = fileinfo.OpenWrite();
    file.WriteByte(0xF);
}
finally
{
    // Check for null because OpenWrite might have failed. 
    if (file != null)
    {
        file.Close();
    }
}

C# 言語仕様

詳細については、「C# 言語仕様」を参照してください。言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。

参照

関連項目

例外と例外処理 (C# プログラミング ガイド)

try-catch (C# リファレンス)

try-finally (C# リファレンス)

try-catch-finally (C# リファレンス)

using ステートメント (C# リファレンス)

概念

C# プログラミング ガイド

その他の技術情報

C# リファレンス