1. ホーム
  2. c#

[解決済み] catch, when "で例外をキャッチする

2022-10-20 12:22:42

質問

C#の新しい機能で、特定の条件が満たされたときにキャッチハンドラを実行することができることを知りました。

int i = 0;
try
{
    throw new ArgumentNullException(nameof(i));
}
catch (ArgumentNullException e)
when (i == 1)
{
    Console.WriteLine("Caught Argument Null Exception");
}

私は、これがいつ役に立つかもしれないかを理解しようとしています。

1つのシナリオは次のようなものでしょう。

try
{
    DatabaseUpdate()
}
catch (SQLException e)
when (driver == "MySQL")
{
    //MySQL specific error handling and wrapping up the exception
}
catch (SQLException e)
when (driver == "Oracle")
{
    //Oracle specific error handling and wrapping up of exception
}
..

というように、同じハンドラ内で、ドライバのタイプに応じて異なるメソッドに委譲することができます。これでコードがわかりやすくなったでしょうか?おそらく違います。

私が考えることができる別のシナリオは、次のようなものです。

try
{
    SomeOperation();
}
catch(SomeException e)
when (Condition == true)
{
    //some specific error handling that this layer can handle
}
catch (Exception e) //catchall
{
    throw;
}

これもまた、こんな感じで。

try
{
    SomeOperation();
}
catch(SomeException e)
{
    if (condition == true)
    {
        //some specific error handling that this layer can handle
    }
    else
        throw;
}

catch, when' 機能を使用すると、ハンドラ内で特定のユースケースを処理する場合と比較して、ハンドラがスキップされ、スタックの巻き戻しがより早く行われるため、例外処理が速くなりますか?また、この機能により適合し、グッドプラクティスとして採用できる特定のユースケースはありますか?

どのように解決するのですか。

キャッチブロックでは既に タイプ をフィルタリングすることができます。

catch (SomeSpecificExceptionType e) {...}

when 節を使うと、このフィルタを一般的な式に拡張することができます。

このように を使うと when 節を使うことになります。 タイプ が明確でなく、ここで例外を処理すべきかどうか判断できない場合。


一般的な使用例として、例外タイプは実際には ラッパー であり、複数の異なる種類のエラーのためのラッパーです。

私が実際に使用したケースを紹介します(VBでは、すでにかなり以前からこの機能があります)。

try
{
    SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
    // Handle the *specific* error I was expecting. 
}

同じく SqlException と同じで、これも ErrorCode プロパティも持っています。代替案はこのようなものでしょう。

try
{
    SomeLegacyComOperation();
}
catch (COMException e)
{
    if (e.ErrorCode == 0x1234)
    {
        // Handle error
    }
    else
    {
        throw;
    }
}

というのは、間違いなく、よりエレガントでなく はスタックトレースを少し崩します。 .

さらに、同じ タイプ の例外を同じtry-catch-blockの中で2回言及することができます。

try
{
    SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
    ...
}
catch (COMException e) when (e.ErrorCode == 0x5678)
{
    ...
}

がなければできないことですが when の条件なしでは不可能です。