关于.net:finally块有什么意义?

关于.net:finally块有什么意义?

What is the point of the finally block?

除了语法,两者之间有什么区别

1
2
3
4
5
6
7
try {
}
catch() {
}
finally {
    x = 3;
}

1
2
3
4
5
6
try {
}
catch() {
}

x = 3;

编辑:.NET 2.0中?

所以

1
2
3
4
5
6
7
try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

在行为上是等效的?


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


视语言而定,因为语义上可能会有一些细微的差异,但是想法是,即使try块中的代码引发异常,它也将始终(几乎)执行。

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

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


在Java中:

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


最后尝试捕获是非常重要的构造。您可以确定,即使引发异常,也会执行finally块中的代码。处理外部资源以释放它们非常重要。垃圾收集不会帮您做到这一点。最后,您不应该具有return语句或引发异常。可以这样做,但这是一种不好的做法,并且可能导致不可预测的结果。

如果您尝试以下示例:

1
2
3
4
5
try {
  return 0;
} finally {
  return 2;
}

结果将是2 :)

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


有以下几点使finally块有用:

  • 如果从try或catch块返回,则在将控制权交还给调用函数之前,finally块仍将执行
  • 如果catch块内发生异常,或者try块内发生未捕获的异常,则finally块中的代码仍将执行。
  • 这些使块最终成为关闭文件句柄或套接字的绝佳选择。


    在尝试和捕获为空的情况下,没有区别。否则,您可以确定将执行finally。

    例如,如果您在catch块中抛出一个新的Exception(重新抛出),则仅当该赋值位于finally块中时,才会执行该赋值。

    通常,finally用于在您自己之后清理(关闭DB连接,文件句柄等)。

    最后,您永远不要使用控制语句(返回,中断,继续),因为这可能是维护的噩梦,因此被认为是不好的做法


    即使抛出异常或到达return语句(尽管可能与语言相关),也会始终调用finally块(不是很总是...)。这是一种清理方法,您知道它将始终被调用。


    @iAn和@mats:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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();  
    }

    最终,代码块使您作为开发人员可以自己整理一下,而不管try {}代码块中的代码前面的操作遇到了什么错误,并且其他人已经指出了这一点,这主要是在释放资源的保护下-关闭指针/套接字/结果集,将连接返回池等

    @mats是非常正确的,它总是存在"硬"故障的可能性-最后,块不应包含关键任务代码,而这些代码始终应在try {}中以事务方式完成

    再次@mats-真正的好处是它允许您将异常抛出自己的方法之外,并且仍然保证您可以整理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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没有什么意义,这也许就是为什么直到最近才在编程语言中不存在它的原因。大多数说明stream.close()的示例都可能导致空引用异常,因此您仍然必须测试它是否为空。

    是的,如果您从try{}内部返回,则finally仍会运行。但这是好习惯吗?看起来像体操,不妨带回goto。为什么不等待并在阻止之后返回? finally {}所做的只是在代码中添加两行或三行。


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


    因此,您可以清理在try块中初始化的所有打开的连接等。如果您打开了一个连接,然后发生了异常,则该异常将无法正确关闭。这种类型的情况就是finally块的用途。


    finally块与try / catch的作用域相同,因此您可以访问其中定义的所有变量。

    假设您有一个文件处理程序,这就是编写方式的区别。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try
    {
       StreamReader stream = new StreamReader("foo.bar");
       stream.write("foo");
    }
    catch(Exception e) { } // ignore for now
    finally
    {
       stream.close();
    }

    相比

    1
    2
    3
    4
    5
    6
    7
    8
    9
    StreamReader stream = null;
    try
    {
        stream = new StreamReader("foo.bar");
        stream.write("foo");
    } catch(Exception e) {} // ignore

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

    请记住,尽管最终里面的任何内容都不能保证运行。想象一下,您收到异常终止信号,窗户崩溃或电源关闭。最终依赖于业务关键代码是不好的。


    在发生未处理的异常的情况下,finally中的所有代码均会运行。通常,finally代码用于使用.dispose()清理非托管代码的本地声明。


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

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

    我猜它在.NET中类似吗?


    @Ed,您可能会想到catch(...)之类的东西,它会捕获C ++中未指定的异常。

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

    Microsoft最终会在C#上提供帮助页面


    推荐阅读

      linux退出编辑命令?

      linux退出编辑命令?,状态,电脑,编辑,命令,文件,模式,键盘,文件名,冒号,界面,l

      linux编辑文件的命令?

      linux编辑文件的命令?,系统,地址,工作,状态,命令,电脑,信息,管理,目录,终端,l

      类似linux的命令编辑?

      类似linux的命令编辑?,环境,地址,命令,状态,工作,信息,情况,文件,目录,编辑,w

      linux编辑一条命令?

      linux编辑一条命令?,状态,工作,命令,系统,信息,代码,设备,数字,标准,正规,lin

      linux命令编辑器与?

      linux命令编辑器与?,环境,档案,标的,数字,名称,数据,正规,名字,命令,光标,Lin

      linux里的编辑命令?

      linux里的编辑命令?,档案,状态,系统,第一,发行,工作,名字,命令,终端,模式,lin

      linux命令编辑文件?

      linux命令编辑文件?,系统,状态,电脑,命令,数据,标准,不了,名称,发行,网络,Lin

      linux编辑文本命令行?

      linux编辑文本命令行?,工作,系统,信息,状态,地址,命令,管理,标准,目录,文件,L

      linux编辑器保存命令?

      linux编辑器保存命令?,状态,网络,系统,电脑,命令,编辑,文件,位置,终端,模式,l

      linux文本编辑命令?

      linux文本编辑命令?,工作,系统,地址,信息,环境,基础,命令,入口,网站,技术,lin

      linux启动命令编辑?

      linux启动命令编辑?,系统,工作,状态,发行,终端,文件,图片,环境,时间,设备,lin

      linux脚本编辑命令行?

      linux脚本编辑命令行?,系统,工作,命令,脚本,网上,设计,环境,业务,地址,时间,l

      linux编辑不保存命令?

      linux编辑不保存命令?,状态,档案,命令,系统,不了,电脑,编辑,文件,终端,模式,l

      linux下命令退出编辑?

      linux下命令退出编辑?,状态,电脑,编辑,情况,软件,盘中,命令,文件,模式,分区,L

      linux命令的编辑命令?

      linux命令的编辑命令?,工作,地址,系统,状态,信息,命令,目录,电脑,管理,标准,l

      linux程序编辑命令?

      linux程序编辑命令?,系统,地址,标准,命令,数据,数字,基础,单位,终端,编辑,如

      linux中常用命令语法?

      linux中常用命令语法?,工作,地址,系统,信息,目录,标准,基础,命令,文件,常用

      linux退出编辑的命令?

      linux退出编辑的命令?,状态,时间,电脑,档案,命令,编辑,文件,盘中,系统,模式,l

      linux退出编辑命令6?

      linux退出编辑命令6?,系统,服务,电脑,代码,信息,环境,正规,数据,编辑,终端,li

      linux中ex编辑命令?

      linux中ex编辑命令?,系统,工作,发行,地址,命令,终端,文件,信息,标准,入口,LIN