finally 块有什么意义?

发布于 2024-07-05 12:39:22 字数 317 浏览 11 评论 0原文

edit:有什么区别

try {
}
catch() {
}
finally {
    x = 3;
}

edit:和

try {
}
catch() {
}

x = 3;

除了语法之外, .NET 2.0 中的


? 那么

try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

行为上是等价的吗?

Syntax aside, what is the difference between

try {
}
catch() {
}
finally {
    x = 3;
}

and

try {
}
catch() {
}

x = 3;

edit: in .NET 2.0?


so

try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

is behaviourally equivalent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

高速公鹿 2024-07-12 12:39:22

finally 块将始终被调用(实际上并不是 总是 ...)抛出异常或到达返回语句(尽管这可能取决于语言)。 这是一种您知道总会被调用的清理方法。

The finally block will always be called (well not really always ... ) even if an exception is thrown or a return statement is reached (although that may be language dependent). It's a way to clean up that you know will always be called.

巡山小妖精 2024-07-12 12:39:22

作为开发人员,finally 块允许您自行清理,无论 try{} 块中的前面代码的操作是否遇到错误,并且其他人已经指出了这一点,这主要属于释放资源的范畴 - 关闭指针/套接字/结果集,返回到池的连接等。

@mats 是非常正确的,总是存在“硬”故障的可能性 - finally 块不应该包含关键任务代码,这些代码应该始终在 try 内以事务方式完成{}

@mats 再次 - 真正的美妙之处在于,它允许您从自己的方法中抛出异常,并且仍然保证您整理完毕:

try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally
{
stream.close();
}

因此,我们可以捕获多种类型的异常,以不同的方式处理它们(第一个允许执行任何超出 try{} 的内容,第二个有效返回),但总是干净利落地清理干净。

Finally blocks permit you, as a developer, to tidy up after yourself, regardless of the actions of preceeding code in the try{} block encountered errors, and have others have pointed out this, is falls mainly under the umbrella of freeing resources - closing pointers / sockets / result sets, returning connections to a pool etc.

@mats is very correct that there is always the potential for "hard" failures - finally blocks shouldn't include mission critical code, which should always be done transactionally inside the try{}

@mats again - The real beauty is that it allows you throw exceptions back out of your own methods, and still guarantee that you tidy up:

try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally
{
stream.close();
}

So, we can catch many types of exception, process them differently (the first allows execution for anything beyond the try{}, the second effectively returns), but always neatly and tidily clear up.

傲影 2024-07-12 12:39:22

@iAn 和@mats:

我不会“拆除”finally {} 中在 try {} 中“设置”的任何内容。 最好将流创建拉到 try {} 之外。 如果您需要处理流创建上的异常,则可以在更大的范围内完成。

StreamReader stream = new StreamReader("foo.bar");  
try {
    mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally {
    stream.close();  
}

@iAn and @mats:

I would not "tear down" anything in finally {} that was "set up" within the try {} as a rule. Would be better to pull the stream creation outside of the try {}. If you need to handle an exception on stream create this could be done in a greater scope.

StreamReader stream = new StreamReader("foo.bar");  
try {
    mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally {
    stream.close();  
}
断舍离 2024-07-12 12:39:22

因此您可以清理在 try 块中初始化的任何打开的连接等。 如果您打开连接然后发生异常,则该异常将无法正确关闭。 这种场景就是finally 块的用途。

So you can clean up any open connections, etc. initialized in the try block. If you opened a connection and then an exception occurred, that exception would not be properly closed. This type of scenario is what the finally block is for.

绅刃 2024-07-12 12:39:22

这不是一个答案,而是一个批评。 这个问题了,但一直困扰着我。 我在这里找到它是有原因的。 我已经阅读了每个答案,但在我看来,没有人真正经过深思熟虑。

我真的认为finally没有什么好处,这可能就是为什么它直到“最近”才出现在编程语言中。 大多数声明 stream.close() 的示例都可能导致空引用异常,因此您仍然需要测试它是否为空。

是的,如果您从 try{} 中返回,finally 仍然会运行。 但这是好的做法吗? 这看起来像是心理体操,不妨把goto带回来。 为什么不等待,并在块之后返回? finally {} 所做的就是向您的代码添加两到三行。

This is not an answer, but a critique. This question is old, but this has always bothered me. I found it here for a reason. I've read every answer and it looks to me that nobody really thought it through.

I really think there is no good point to finally, which may be why it didn't exist in programming languages until "recently". Most of the examples stating stream.close() can cause null reference exceptions, so you still have to test if it's null.

Yes, if you return from within try{}, finally still runs. But is that good practice? It seems like mental gymnastics, might as well bring goto back. Why not wait, and return after the block? All that finally {} does, is add two or three lines to your code.

無處可尋 2024-07-12 12:39:22

无论您是否捕获到异常,finally 块都应该执行。
请参阅尝试/捕获/最终示例

The finally block is supposed to execute whether you caught the exception or not.
See Try / Catch / Finally example

李不 2024-07-12 12:39:22

在 Java 中,您可以将它用于任何您想要执行的操作,无论您是否使用了“返回”、只是运行了 try 块,还是捕获了异常。

例如,关闭数据库会话或 JMS 连接,或取消分配某些操作系统资源。

我猜它在.NET 中是类似的?

In Java, you use it for anything that you want to execute regardless of whether you used a "return", just ran through the try block, or had an exception caught.

For example, closing a database session or a JMS connection, or deallocating some OS resource.

I am guessing it is similar in .NET?

久伴你 2024-07-12 12:39:22

即使发生未处理的异常,finally 中的任何代码也会运行。 通常,finally 代码用于使用 .dispose() 清理非托管代码的本地声明。

Any code in the finally is ran in the even in the event of an unhandled exception. Typically the finally code is used to clean up local declarations of unmanaged code using .dispose().

土豪我们做朋友吧 2024-07-12 12:39:22

@Ed,你可能会想到类似的东西在 C++ 中捕获非指定异常的 catch(...)

finally 是无论catch 块中发生什么情况都会执行的代码。

Microsoft 在 C# 的 try-finally 上有一个帮助页面

@Ed, you might be thinking of something like a catch(...) that catches a non-specified exception in C++.

But finally is code that will get executed no matter what happens in the catch blocks.

Microsoft has a help page on try-finally for C#

梦巷 2024-07-12 12:39:22

好吧,一方面,如果您在 try 块内返回,finally 仍然会运行,但 try-catch-finally 块下面列出的代码不会。

Well, for one thing, if you RETURN inside your try block, the finally will still run, but code listed below the try-catch-finally block will not.

橘虞初梦 2024-07-12 12:39:22

取决于语言,因为可能存在一些轻微的语义差异,但想法是它会(几乎)始终执行,即使 try 块中的代码引发异常。

在第二个示例中,如果 catch 块中的代码返回或退出,则 x = 3 将不会被执行。 首先它会的。

在.NET平台中,在某些情况下不会执行finally块:
安全异常、线程暂停、计算机关闭:)等。

Depends on the language as there might be some slight semantic differences, but the idea is that it will execute (almost) always, even if the code in the try block threw an exception.

In the second example, if the code in the catch block returns or quits, the x = 3 will not be executed. In the first it will.

In the .NET platform, in some cases the execution of the finally block won't occur:
Security Exceptions, Thread suspensions, Computer shut down :), etc.

习惯成性 2024-07-12 12:39:22

在 Java 中:

Finally 总是被调用,无论异常是否在 catch() 中被正确捕获,或者实际上是否有 catch。

In Java:

Finally always gets called, regardless of if the exception was correctly caught in catch(), or in fact if you have a catch at all.

爱本泡沫多脆弱 2024-07-12 12:39:22

try catch finally 是非常重要的结构。 可以确定的是,即使抛出异常,finally 块中的代码也会被执行。 处理外部资源并释放它们非常重要。 垃圾收集不会为你做到这一点。 在最后一部分中,您不应该有 return 语句或抛出异常。 这样做是可能的,但这是一种不好的做法,并且可能会导致不可预测的结果。

如果您尝试这个示例:

try {
  return 0;
} finally {
  return 2;
}

结果将是 2:)

与其他语言的比较: 从最后返回

try catch finally is pretty important construct. You can be sure that even if an exception is thrown, the code in finally block will be executed. It's very important in handling external resources to release them. Garbage collection won't do that for you. In finally part you shouldn't have return statements or throw exceptions. It's possible to do that, but it's a bad practice and can lead to unpredictable results.

If you try this example:

try {
  return 0;
} finally {
  return 2;
}

The result will be 2:)

Comparison to other languages: Return From Finally

極樂鬼 2024-07-12 12:39:22

使finally块变得有用的因素有很多:

  1. 如果从try或catch块返回,则在控制权返回给调用函数之前,finally块仍然会被执行
  2. 如果catch块内发生异常,或者未捕获的异常try 块中发生类型异常,finally 块中的代码仍然执行。

这些使得finally块非常适合关闭文件句柄或套接字。

There are several things that make a finally block useful:

  1. If you return from the try or catch blocks, the finally block is still executed, right before control is given back to the calling function
  2. If an exception occurs within the catch block, or an uncaught type of exception occurs in the try block, the code in the finally block is still executed.

These make finally blocks excellent for closing file handles or sockets.

我家小可爱 2024-07-12 12:39:22

在 try 和 catch 为空的情况下,没有区别。 否则你可以确定,finally 将会被执行。

例如,如果您在 catch 块中抛出一个新的异常(重新抛出),那么只有在finally 块中的赋值才会被执行。

通常,finally 用于在您自己之后进行清理(关闭数据库连接、文件句柄等)。

你不应该在finally中使用控制语句(return、break、 continue),因为这可能是维护的噩梦,因此被认为是不好的做法

In the case, that the try and the catch are empty, there is no difference. Otherwise you can be sure, that the finally will be executed.

If you, for example throw a new Exception in your catchblock (rethrow), than the assignment will only be executed, if it is in the finally-block.

Normally a finally is used to clean up after yourself (close DB-connections, File-Handles and the likes).

You should never use control-statements (return, break, continue) in a finally, as this can be a maintenance nightmare and is therefore considered bad practice

饭团 2024-07-12 12:39:22

finally 块与 try/catch 位于同一范围内,因此您可以访问其中定义的所有变量。

想象一下您有一个文件处理程序,这就是它的编写方式的差异。

try
{
   StreamReader stream = new StreamReader("foo.bar");
   stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
   stream.close();
}

相比之下,

StreamReader stream = null;
try
{
    stream = new StreamReader("foo.bar");
    stream.write("foo");
} catch(Exception e) {} // ignore

if (stream != null)
    stream.close();

记住,finally 里面的任何东西都不能保证运行。 想象一下,您收到中止信号、窗口崩溃或断电。 依赖于最终的业务关键代码是不好的。

The finally block is in the same scope as the try/catch, so you will have access to all the variables defined inside.

Imagine you have a file handler, this is the difference in how it would be written.

try
{
   StreamReader stream = new StreamReader("foo.bar");
   stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
   stream.close();
}

compared to

StreamReader stream = null;
try
{
    stream = new StreamReader("foo.bar");
    stream.write("foo");
} catch(Exception e) {} // ignore

if (stream != null)
    stream.close();

Remember though that anything inside finally isn't guaranteed to run. Imagine that you get an abort signal, windows crashes or the power is gone. Relying on finally for business critical code is bad.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文