サーチ…


備考

関連:

例外をキャッチする

例外的な状況でコードで例外をスローすることができます。これの例としては、

呼び出し元は、これらの例外を「キャッチ」することで処理できます。以下の場合にのみ実行してください。

  • それは実際に例外的な状況を解決したり、適切に回復することができます。
  • 例外を再スローする必要がある場合に有用な例外に追加のコンテキストを提供することができます(再スローされた例外は例外ハンドラによってコールスタックの上位にキャッチされます)

例外をキャッチしないことを選択することは、それがより高いレベルで処理されることが意図されている場合には完全に有効であることに留意されたい。

例外をキャッチするには、潜在的にスローするコードをtry { ... }ブロックに次のようにラップし、 catch (ExceptionType) { ... }ブロックで処理できるcatch (ExceptionType) { ... }ます。

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}

finallyブロックの使用

例外が発生したかどうかに関係なく、 try-finallyまたはtry-catch-finallyfinally { ... }ブロックは常に実行されます(例外はStackOverflowExceptionがスローされたか、 Environment.FailFast() )。

try { ... }ブロックで取得したリソースを安全に解放またはクリーンアップするために利用できます。

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream = null;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

キャッチされた例外のキャッチと再スロー

例外をキャッチして何かをしたいが、例外のために現在のコードブロックの実行を続行できないときは、コールスタック内の次の例外ハンドラに例外を戻すことが必要な場合があります。これを行うには良い方法と悪い方法があります。

private static void AskTheUltimateQuestion()
{
    try
    {
        var x = 42;
        var y = x / (x - x); // will throw a DivideByZeroException

        // IMPORTANT NOTE: the error in following string format IS intentional
        // and exists to throw an exception to the FormatException catch, below
        Console.WriteLine("The secret to life, the universe, and everything is {1}", y); 
    }
    catch (DivideByZeroException)
    {
        // we do not need a reference to the exception
        Console.WriteLine("Dividing by zero would destroy the universe.");

        // do this to preserve the stack trace:
        throw;
    }
    catch (FormatException ex)
    {
        // only do this if you need to change the type of the Exception to be thrown 
        // and wrap the inner Exception

        // remember that the stack trace of the outer Exception will point to the
        // next line

        // you'll need to examine the InnerException property to get the stack trace
        // to the line that actually started the problem

        throw new InvalidOperationException("Watch your format string indexes.", ex);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);

        // do not do this, because the stack trace will be changed to point to
        // this location instead of the location where the exception
        // was originally thrown:
        throw ex; 
    }
}

static void Main()
{
    try
    {
        AskTheUltimateQuestion();
    }
    catch
    {
        // choose this kind of catch if you don't need any information about 
        // the exception that was caught

        // this block "eats" all exceptions instead of rethrowing them
    }
}

あなたは例外タイプと例外プロパティ(C#6.0の新機能、VB.NETでもう少し利用可能です(引用が必要です))でフィルタリングすることもできます:

ドキュメンテーション/ C#/新機能

例外フィルタ

C#6.0の例外は、 when演算子を使用してフィルタリングできるためです。

これは単純なifを使用するのと似ていますが、 whenの条件が満たされていないwhenはスタックを巻き戻しません。

try
{ 
  // ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
  // ...
}

同じ情報はC#6.0の機能にあります: 例外フィルタ

catchブロック内での例外の再試行

catchブロック内では、例外値を指定せずにthrowキーワードを単独で使用することができ、 catchされたばかりの例外を再現することができます。例外を再発行すると、元の例外は例外処理チェーンを継承し、その呼び出しスタックまたは関連するデータは保持されます。

try {...}
catch (Exception ex) {
  // Note: the ex variable is *not* used
  throw;
}

一般的なアンチパターンは代わりthrow exthrow exすることです。スタックトレースの次の例外ハンドラのビューを制限するという効果があります。

try {...}
catch (Exception ex) {
  // Note: the ex variable is thrown
  //  future stack traces of the exception will not see prior calls
  throw ex;  
}

一般的に使用してthrow exスタックトレースを検査し、将来の例外ハンドラのみにまでさかのぼるとして呼び出しを見ることができますよう、望ましくないthrow exex変数を省略し、 throwキーワードだけを使用すると、元の例外は"バブルアップ"します。

情報を保持しながら別のメソッドから例外をスローする

例外をキャッチして、元の例外スタックを保持しながら、別のスレッドまたはメソッドから例外をスローすることが必要な場合があります。 ExceptionDispatchInfoこれを行うことができExceptionDispatchInfo

using System.Runtime.ExceptionServices;

void Main()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }
    
    Foo(capturedException);
}

void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // Do stuff

    if (capturedException != null)
    {
        // Exception stack trace will show it was thrown from Main() and not from Foo()
        exceptionDispatchInfo.Throw();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow