11

私はこのパターンを数回見ました:

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

そして、私は疑問に思っていました: ロールバックに catch を使用するよりもなぜこれが優れているのですか?

        try
        {
            DoSomething();
        }
        catch
        {
            Rollback();
            throw;
        }

失敗時に変更を確実にロールバックする 2 つの方法の違いは何ですか?

4

6 に答える 6

4

質問に実際には関係がない場合でも、ここにいくつかのコードを投稿します(後で削除します)。

このプログラムでは:

using System;

namespace testcs
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                try
                {
                    foo();
                    foo();
                    foo();
                }
                catch
                {
                    throw;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void foo()
        {
            throw new Exception("oops");
        }
    }
}

スタック トレース (行番号を見てください!) は保持されmainますが、関数内には "19 行目" が表示されます。この行は、呼び出されthrow実際の行(13 行目) です。foo()

于 2012-05-23T14:29:13.297 に答える
2

このfinallyステートメントは通常、リソースのクリーンアップに使用されます。Rollback()例外がトランザクションをロールバックする唯一の理由ではない場合、メソッドをそこで使用しても問題ない可能性があります。Close()またはDispose()メソッドは、finally ブロックに入る最有力候補です。

ただし、例外をスローする可能性のあるものはそこで実行したくありません。

于 2012-05-23T14:19:11.457 に答える
2

これが単なる逸話的な証拠ではないかどうかはわかりませんが、私は個人的にこのパターンを非常に実用的な理由で使用していDoSomethingます。例外をスローすると、Visual Studio デバッガーはDoSomething最初のバージョンで例外が発生した場所で中断しますthrow;2 番目のバージョンで中断します。Rollbackこれにより、すべてをクリーンアップする前にアプリケーションの状態を調べることができます。

スクリーンショット

于 2012-05-23T14:30:08.187 に答える
2

この特定のコードで、キャッチする例外のタイプを気にしない場合は、次を使用します。

try
{
   DoSomething();
   ok = true;
}
finally
{
    if(!ok)Rollback();
}

これにより、コール スタックが元の形式で 100% 保持されます。また、次のような例外処理を使用する場合:

try
{
   DoSomething();
   ok = true;
}
catch(FirstExcetionType e1)
{
    //do something
}
catch(SecondExcetionType e2)
{
    //do something
}
catch(Exception e3)
{
    //do something
}
finally
{
    if(!ok)Rollback();
}

最後に finally を使用すると、すべての catch ステートメントからロールバックを呼び出すよりもコードが読みやすくなります。

于 2012-05-23T14:31:12.533 に答える
1

finally例外のキャッチ時だけでなく、常に実行されます。

確かに、この特定のケースでは、ロールバックはエラーが発生した場合にのみ必要ですが、一般的なパターンとして、try-finallyリソース管理にはロールバックの方が役立つ場合があります (リソースを常に適切に管理する必要がある場合Close()) Dispose()。特に、コードの作成者が Java のバックグラウンドを持ち、このイディオムがより広まっている場合はなおさらです。

于 2012-05-23T14:16:58.293 に答える
0

ここでの明確な目標はRollback、エラーが発生した場合に呼び出されるようにすることです。どちらのコード スニペットもこの目標を達成します。try1 つ目は、ブロックの最終行に到達したことを検証する、常に実行される finally を使用します。2 番目はエラーをキャッチし、トランザクションをロールバックしてから、キャッチされた例外を再スローします。どちらのスニペットの結果として、例外がスローされると、ロールバックが発生し、次のレベルまでバブリングします。

このプロジェクトは Java から移植されたものだとおっしゃいました。Java では、C# で を使用して行う方法と同様に、例外を再スローでき ます。また、コール スタックを引き続き維持する新しい例外をスローすることもできます (その他)。2 番目は C# の方が少し明確/単純ですが (それほど多くはありません)、1 番目は実際に Java で書かれたとおりに動作するという利点があります。 throw;

于 2012-05-23T14:29:34.990 に答える