6

私がこのようなものを持っていたらどうしますか:

try
{
   //work
}
catch (ArgumentNullException e)
{
   HandleNullException();
   Logger.log("ArgumentNullException " + e);
   DoSomething();
}
catch (SomeOtherException e)
{
   HandleSomeOtherException();
   Logger.log("SomeOtherException " + e);
   DoSomething();
}
catch (Exception e)
{
   HandleException();
   Logger.log("Exception " + e);
   DoSomething();
}

ご覧のとおり、いくつかの異なるケースの例外を処理しようとしています。しかし、例外が発生するたびに、私は常にDoSomething()最後にメソッドを呼び出しています。DoSomething()例外がある場合に呼び出すよりスマートな方法はありますか? finallyブロックを追加してDoSomething()そこに呼び出すと、例外がなくても常に呼び出されます。助言がありますか?

4

6 に答える 6

9

finallyブロックを追加してDoSomething()そこに呼び出すと、例外がなくても常に呼び出されます。

探しているものは、CLI 標準(パーティション IIA、第 18 章) でfault handlerとして知られています。.NET はそれらを実装していますが、C# 言語はそれらを直接サポートしていません。ただし、これらはエミュレートできます。

bool success = false;
try
{
    …
    success = true;
}
catch (…)
{
    …
}
…
finally
{
    if (!success)
    {
        DoSomething();
    }
}

catchここでいくつかの回答が示唆しているように、すべてのハンドラー内にフラグを設定する必要はないことに注意してください。テストを無効にするだけで、tryブロックの最後でフラグを 1 回設定するだけで済みます。

于 2013-01-12T21:43:05.197 に答える
5

実際に冗長性を削除する次のコードを使用できます

try
{
    //work
}
catch (Exception e)
{
    Handle(e);
}

メソッドHandleは次のとおりです。

static void Handle(Exception e)
{
    var exceptionType = e.GetType();
    //Use an if/else block, or use a Dictionary<Type, Action>
    //to operate on your exception
    Logger.log(exceptionType + " " + e);
    DoSomething();
}
于 2013-01-12T21:47:51.393 に答える
2

あなたが今していることは、それが得られるのと同じくらい良いことです。

例外が発生するたびにこの関数を呼び出す必要があるが、それ以外の場合は呼び出す必要がなく、さまざまな例外を処理するための別のコードが必要な場合は、これが最善の方法です。

于 2013-01-12T21:41:42.043 に答える
2

例外がスローされるたびにブール値を設定し、ブール値を使用finallyして確認できます。(または、以下に示すように、反対のことを行い、例外がスローされない場合にのみブール値を設定します:)

bool noException = false;
try
{
    //work
    noException = true;
}
catch (ArgumentNullException e)
{
    HandleNullException();
    Logger.log("ArgumentNullException " + e);
}
catch (SomeOtherException e)
{
    HandleSomeOtherException();
    Logger.log("SomeOtherException " + e);
}
catch (Exception e)
{
    HandleException();
    Logger.log("Exception " + e);
}
finally
{
    if (!noException)
        DoSomething();
}
于 2013-01-12T21:42:47.383 に答える
2

それだけではない理由:

try
{
    //work
}
catch (Exception e)
{
    if (e is ArgumentNullException)
      HandleNullException();
    else if (e is SomeOtherException)
      HandleSomeOtherException();
    else
      HandleException();
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

ログに記録される型名は実際のランタイム型になるため、たとえば、ケース 3"IndexOutOfRangeException"の代わりにログに記録される可能性がありますが"Exception"、これは現在のものよりも改善されていると思います。

編集:if上記のコードは、 –<code>else if ロジックが型をチェックすると見栄えが悪くなります。ポリモーフィズムを導入すると、より美しくなる可能性があります。

try
{
    //work
}
catch (HandleableException e)
{
    e.Handle();  // this calls a **virtual** method, each override does what's relevant
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

もちろん、問題のクラスの一部を変更できない場合、それらにメソッドExceptionを与えることは不可能です。Handle()(インスタンス メソッド.Handle()ではなく) 拡張メソッドにすることもできますがvirtual、その場合、型チェック (醜いコード) をそのメソッド内で行う必要があります。すると、これはイブの答えと非常によく似たものになります。

于 2013-01-12T22:32:51.653 に答える
1

あなたはこれを行うことができます:

Exception caughtException = null;
try {
    ...
} catch(ExceptionType1 e1) {
    ...
    caughtException = e1;
} catch(ExceptionType2 e2) {
    ...
    caughtException = e2;
} catch(ExceptionType3 e3) {
    ...
    caughtException = e3;
}
if (caughtException != null) {
    // Put your common exception code here
    DoSomenthing();
    // You can pass caughtException to functions, too
    LogException(caughtException);
}

caughtExceptionnull例外がキャッチされない限り。それを使用して、呼び出すDoSomenthingかどうかを決定できます。

于 2013-01-12T21:43:02.243 に答える