What is the purpose of “finally” in try/catch/fina

2019-02-03 04:59发布

The syntax will change from language to language, but this is a general question.

What is the difference between this....

try
{
     Console.WriteLine("Executing the try statement.");
     throw new NullReferenceException();
}
catch (NullReferenceException e)
{
     Console.WriteLine("{0} Caught exception #1.", e);
}       
finally
{
     Console.WriteLine("Executing finally block.");
}

and this....

try
{
    Console.WriteLine("Executing the try statement.");
    throw new NullReferenceException();
}
catch (NullReferenceException e)
{
    Console.WriteLine("{0} Caught exception #1.", e);
}        
Console.WriteLine("Executing finally block.");

I keep seeing it being used, so I assume there's a good reason to use finally, but I can't figure out how it's any different from just putting code after the statement since it will still run.

Is there ever a scenario where finally doesn't run?

10条回答
Lonely孤独者°
2楼-- · 2019-02-03 05:25

I don't know C#, but the purpose of a finally block in Java-ish languages is to ensure that system resources are relinquished, especially if garbage collection is irregular. It's the same principle for all. Consider the block

InputStream is = new FileInputStream("foo.txt");
OutputStream os = new FileOutputStream("D:/nonexistent/directory/bar.txt");
// Throws a FileNotFoundException.

The variable is is created successfully, and takes up system resources. Processes can only use a fixed number of file handles at a time. The variable os is never created, and an exception is thrown, and bubbles up to the caller. In the process, is goes out of scope, and becomes eligible for garbage collection.

However garbage collections are never guaranteed to happen, or they may happen at some indefinite time in the future. So, the system resources taken by is may never be freed. This can be costly, or can crash the program if it happens enough times. So, finally blocks were put into Java. Other languages have similar constructs. In C++, destructors are invoked deterministically. LISPy languages have unwind-protect, but those are usually packaged in with-foo macros.

In Java 6 and lower, one would do this:

try {
    is = new FileInputStream("foo.txt");
    os = new FileOutputStream("D:/nonexistent/directory/bar.txt");
    // work...
} finally {
    if (is != null) {
        try {
            is.close();
        } catch (IOException ignored) {}
    }
    if (os != null) {
        try {
            os.close();
        } catch (IOException ignored) {}
    } 
}

You can't just call is.close() because that might throw, and then os will never be closed. You have to check for null too. Sane people used Jakarta Commons-IO's IOUtils.closeQuietly() methods to replace the block:

} finally {
    IOUtils.closeQuietly(is);
    IOUtils.closeQuietly(os);
}

But Java 7 introduced a better solution: try-with-resources. C# 4 probably came first with something similar, Microsoft being quicker on the uptake than Snoracle.

try (
    is = new FileInputStream("foo.txt"),
    os = new FileOutputStream("D:/nonexistent/directory/bar.txt")
) {
    // work...
}
查看更多
The star\"
3楼-- · 2019-02-03 05:26

It really depends - some other answers have very good reasons to use a Finally block. But I think the best reason is because you're doing exception handling. Things you do in a Finally block typically involve cleaning up resources to ensure proper continuation, regardless of whether or not an exception was thrown - to me that's still part of the exception handling, at least part of a "try something" operation.

IMHO the Finally scope highlights the fact that its code contains stuff that deserves special attention in case of an exception.

查看更多
倾城 Initia
4楼-- · 2019-02-03 05:26

finally block is guaranted to be excuted. So, in your example, results of both cases are looks same. but if you use return or throw in your catch block, you can see what is difference.

查看更多
相关推荐>>
5楼-- · 2019-02-03 05:30
try
{
    throw new Exception("Error!");
}
catch (Exception ex)
{
    throw new Exception(ex, "Rethrowing!");
}
finally
{
    // Will still run even through the catch kicked us out of the procedure
}

Console.WriteLine("Doesn't execute anymore because catch threw exception");
查看更多
登录 后发表回答