说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

细微之处见真章 为什么要在try-catch-finally里加大括号

HTML文档下载 WORD文档下载 PDF文档下载
相信每个程序员对try-catch-finally都不陌生,并且都知道它是用来处理异常的。那么你是否思考过,在if这些语句里不使用大括号编译器即可解析,可是为什么在try-catch-finally里就必须要使用大括号呢?

用C语言开发的程序员通常会使用if、while、for等组建一条语句或者是一个代码块。

  1. if (x)  
  2.   M(); 
  1. if (x)  
  2. {  
  3.   M();  
  4.   N();  

然而,语言设计者好像对此并不关心。像if、while、for等这些可以作为单独的一条语句,并且被大括号包围起来的部分也可以作为单独的代码块。

无论我们对语法进行怎样的思考,try-catch-finally肯定与if等语句是不同的。try-catch-finally需要一个支撑块(braced block)。

在我们深入try-catch-finally之前,先让我们换换思绪,来思考下面的问题。明确的循环结构(looping structures):

  1. while(A())  
  2.   while(B())  
  3.     C(); 

虽然没有大括号,但是内部while语句与外部while进行了很好地组合,所以没有括号也不影响阅读与理解。但如果把这种情况应用到if语句上,就会遇到著名的“dangling else ”问题。

  1. if (A())  
  2.   if (B())  
  3.     C();  
  4. else 
  5.   D(); 

好吧,请问这样的缩进正确吗?else D()是对应内部的if还是外部的if呢?

答案当然是与内部if相匹配的,else与最近的if语句相匹配(就近原则)。编程语言中空格并不重要,但在阅读代码时常常会因为错误的缩进格式而导致理解错误。在C或者C++中我也看到写的很糟糕的宏,并且导致了“dangling-else”问题。

在语言中添加try-catch-finally,设计者希望避免“dangling-else”问题。假设如果在try、catch或finally后可以插入任意行代码,而不是放置一段代码块,那么对于这样的代码片段,你会如何解释呢?

  1. try 
  2.   try 
  3.     A();  
  4.   catch AException  
  5.     B();  
  6. catch BException  
  7.   C(); 

不禁要问,这样的缩进正确吗?B()是受保护的?我们是否应该换种方式编写呢:

  1. try 
  2. {  
  3.   try 
  4.   {  
  5.     A();  
  6.   }  
  7.   catch AException  
  8.   {  
  9.     B(); // protected by the outer try  
  10.   }  
  11. }  
  12. catch BException  
  13. {  
  14.   C();  

难道上面的也有问题?

  1. try // try without associated catch!  
  2. {  
  3.   try 
  4.   {  
  5.     A();  
  6.   }  
  7.   catch AException  
  8.   {  
  9.     B(); // not protected  
  10.   }  
  11.   catch BException  
  12.   {  
  13.     C();  
  14.   }  

不要试图提出规则来消除这些模棱两可的语法解析,而最好的做法就是使用大括号——可以轻易地避免这种歧义。

有趣的是,从语法角度来看,try代码块完全没有必要。简单地说,任何块都可以跟随着catch代码块或者finally块, try块可以作为隐式代码块。这是一个冗余让代码更可读的典型例子。try关键字可以提醒读者,说明该段控制流需要处理一些异常信息。

此外,分享一个有趣的信息。在最初设计C#语言时,是没有try-catch-finally的,只有try-catch和try-finally。如果想编写try-catch-finally,你还得这样做:

  1. try 
  2. {  
  3.   try 
  4.   {  
  5.     A();  
  6.   }  
  7.   catch AException  
  8.   {  
  9.     B();  
  10.   }  
  11. }  
  12. finally 
  13. {  
  14.   C();  

语言设计者意识到这是种常见的模式并且是不必要的冗长,所以他们允许语法糖消除外部多余的try。但是C#编译器生成的代码正如你上面编写的嵌套一样,因为在CIL层中是没有try-catch-finally。另外,在C#中,if、while等并不是个单独的局部变量声明。

来自:Why are braces required in try-catch-finally?

【MDCC专访】环信CEO刘俊彦:音视频即时通讯将成为技术壁垒 第十七届全国工程建设计算机应用大会在京召开,AMD受邀详解GPU Computing! 哪一门开发语言薪水最高? 借助ArangoDB,带你玩转Google图算法引擎Pregel 【最具价值CTO评选秀】MediaV CTO胡宁:技术女神的自我奋斗 对象不支持此属性和方法 很菜的问题,在线等…… solaris下oracle8i无法备份出来. 求教关于二进制存储的问题 sql server 是不是不支持limit?可以用什么代替呢? 求教关于二进制读取的问题 ImageCreate中文字符问题 各位大哥,请问"计算任意两天相差的天数"的算法是什么 莫名奇妙的问题,正常情况下,在同一个文件夹中的两个类是可以相互调用的吧,可是我在一个类中调用另外一个 怎么就是编译的报错!!请指 网上如何看中央电视台新闻联播 西门子冰箱调温,夏天按钮应调为I还是O因为我家的西 有八个空格.把1,2,3,4,16,17,18,1 西门子洗衣机的型号的含义 西门子洗衣机出现E: 请帮忙整理下2013年1月13日~2月29日关心国 请帮我收集三件2013年国家大事,要带上时间像纪念 老师在黑板上写了从11开始的若干个连续自然数,擦掉 老师在黑板上写若干个从10开始的连续的自然数,10 美一少女持枪照顾5岁男童 男童误将自泰咖啡摊主因招牌与星巴克标志雷同被起北京一日两次发文管控新房价格 调控趋美媒称中国教改“打压”英语不代表西方日将在福岛举办首脑论坛拉拢太平洋岛国谁把便利店搬进了电影院?如画紫薇令人陶醉武汉工行联合高校 开启“信息化迎新400多居民爬上爬下苦不堪言农行“金融知识宣传”走进武汉社区从修真界归来我有一个主神空间伊布的大冒险神道传奇系统美利坚噩梦大连现代博物馆旅游大连贝壳博物馆旅游大连星海会展中心旅游马王堆汉墓旅游炎帝广场旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘