try-catch (C# リファレンス)
更新 : 2007 年 11 月
try-catch ステートメントは、try ブロックと、それに続く catch 句で構成されます。この句にはさまざまな例外のハンドラを指定します。例外がスローされると、共通言語ランタイム (CLR: Common Language Runtime) は、この例外を処理する catch ステートメントを検索します。現在実行されているメソッドに catch ブロックが含まれていない場合、CLR は現在のメソッドを呼び出したメソッドを検索します (この方法で、呼び出しスタックの上位を検索していきます)。catch ブロックが見つからない場合、CLR は未処理例外のメッセージをユーザーに表示し、プログラムの実行を停止します。
try ブロックには、例外を発生させる可能性がある保護されたコードが含まれます。ブロックは、例外がスローされるか、ブロックが正常に終了するまで実行されます。たとえば、次の例では null オブジェクトをキャストしようとすると、NullReferenceException 例外が発生します。
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
catch 句は、引数なしで使用してすべての種類の例外をキャッチできますが、この使用方法は推奨しません。通常は、回復方法が判明している例外のみキャッチするのが適切です。したがって、System.Exception から派生したオブジェクト引数を必ず指定します。以下に例を示します。
catch (InvalidCastException e)
{
}
特定の catch 句は、同一の try-catch ステートメントで複数使用できます。この場合、catch 句は順序どおりにチェックされるため、catch 句の順序が重要になります。例外は、特定性の高い順にキャッチしてください。後のブロックに到達しないように catch ブロックを並べた場合、コンパイラはエラーを発生させます。
throw ステートメントは、catch ステートメントでキャッチされた例外を再びスローするために catch ブロックで使用できます。次に例を示します。
catch (InvalidCastException e)
{
throw (e); // Rethrowing exception e
}
新しい例外もスローできます。これを行うには、キャッチする例外を内部例外として指定します。
catch (InvalidCastException e)
{
// Can do cleanup work here.
throw new CustomException("Error message here.", e);
}
パラメータのない catch 句で処理された例外を再スローする場合、引数のない throw ステートメントを使用します。次に例を示します。
catch
{
throw;
}
try ブロック内では、そこで宣言されている変数だけを初期化します。外部で宣言された変数を初期化すると、ブロックの実行が完了する前に例外が発生する可能性があるためです。たとえば、以下のコード例では、変数 x が try ブロック内で初期化されます。この変数を try ブロックの外側にある Write(x) ステートメントで使おうとすると、コンパイラ エラー "未割り当てのローカル変数 'var' が使用されました。" が発生します。
static void Main()
{
int x;
try
{
// Don't initialize this variable here.
x = 123;
}
catch
{
}
// Error: Use of unassigned local variable 'x'.
Console.Write(x);
}
catch の詳細については、「try-catch-finally」を参照してください。
使用例
例外を発生させる可能性がある ProcessString メソッドへの呼び出しを含む try ブロックの例を次に示します。catch 句には、メッセージを画面に表示するだけの例外ハンドラがあります。throw ステートメントが MyMethod の内側から呼び出されると、システムは catch ステートメントを検索し、メッセージ "Exception caught" を表示します。
class TryFinallyTest
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
string s = null; // For demonstration purposes.
try
{
ProcessString(s);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() Exception caught.
* */
2 つの catch ステートメントを使用する例を次に示します。最初にある、特定性の最も高い例外がキャッチされます。
class ThrowTest3
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
try
{
string s = null;
ProcessString(s);
}
// Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}
// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() First exception caught.
*/
前の例で、特定性の最も低い catch 句から始めると、次のエラー メッセージが表示されます。
A previous catch clause already catches all exceptions of this or a super type ('System.Exception')
ただし、特定性の最も低い例外をキャッチするには、throw ステートメントを次のものと置き換えます。
throw new Exception();
C# 言語仕様
詳細については、「C# 言語仕様」の次のセクションを参照してください。
5.3.3.13 try-catch ステートメント
8.10 try ステートメント
16 例外
参照
処理手順
概念
参照
The try, catch, and throw Statements