Using finally instead of catch

南笙酒味 提交于 2019-12-08 16:37:22

问题


I've seen this pattern a few times now:

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

And I've been wondering: Why is this better than using catch for rollbacks?

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

What are the differences between the two ways of making sure changes are rolled back on failure?


回答1:


The clear goal here is to cause Rollback to be called in the event of any error. Both code snippets accomplish this goal. The first uses a finally, which always runs, that verifies that the last line of the try block was successfully reached. The second catches any errors, rolls back the transaction, and then re-throws the exception that was caught. The result of either snippet is that any exceptions thrown will result in a rollback while still bubbling up to the next level.

You mentioned that the project was ported from Java. In Java, you can re-throw an exception similarly to how you can in C# using throw;. You can also throw a new exception that will still maintain the call stack (et al). The second is a bit clearer/simpler in C# (not by a lot though) and the first has the advantage of actually working in Java as written.




回答2:


I post here some code even if it's not really related to the question (will delete later).

With this program:

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");
        }
    }
}

The stack trace (look at line numbers!) is preserved but inside the main function you'll see "line 19", the line where throw is instead the true line where foo() has been called (line 13).




回答3:


The finally statement is usually used for cleaning up resources. The Rollback() method might be okay to use there if exceptions are not the only reasons to roll back the transaction. Close() or Dispose() methods are prime candidates to end up in the finally block.

However, you do not want to execute anything there that can throw exceptions.




回答4:


If you do not care in this particular code what type of exception you are catching use:

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

This will preserve Call Stack in its original form for 100%. Also if you use exception maching like this:

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

using finally at the end can make your code more readable than calling rollback from every single catch statement.




回答5:


I'm not sure if this is not just anecdotal evidence, but I personally have used this pattern for a very practical reason: When DoSomething throws an exception, the Visual Studio debugger will break in DoSomething where the exception occurs in the first version, while it will break at the throw; in the second version. This allows to inspect the application state before Rollback has cleaned everything up.




回答6:


finally is always executed, not only on catching exceptions.

Granted, in this specific case the rollback is only needed when there was an error, but as a general pattern, the try-finally may be more useful for resource management (where often you need to ensure that you always Close() or Dispose() of your resource properly). Especially if the author of the code is coming from Java background where this idiom is more widespread.



来源:https://stackoverflow.com/questions/10721807/using-finally-instead-of-catch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!