IMO,它们之所以包含在Java和C#中,主要是因为它们已经存在于C ++中。那么,真正的问题是C ++为什么会这样。根据C ++的设计和演变(第16.3节):
该try
关键字是完全冗余的,所以是{ }
除了其中多个语句在try块或一个处理程序实际使用的支架。例如,允许:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
但是,我发现很难解释这一点,因为引入了冗余是为了从混乱的用户中节省支持人员。
编辑:至于为什么这会造成混淆,我认为只需要查看@Tom Jeffery的答案中的不正确断言(尤其是收到的赞成票的数量)就可以意识到会有问题。对于解析器而言,这实际上与将else
s与if
s 匹配没有什么不同-缺少用于强制其他分组的花括号,所有 catch
子句都将与最新的匹配throw
。对于那些包含它的错误的语言,finally
子句也将这样做。从解析器的角度来看,这与当前情况几乎没有什么不同,尤其是从语法的角度来看,实际上没有什么可将这些catch
子句归为一类的了,方括号将由catch
子句,而不是catch子句本身。
从编写解析器的角度来看,差异几乎很小,无法察觉。如果我们从这样的事情开始:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
那么区别将是:
try_clause: 'try' statement
和:
try_clause: 'try' compound_statement
同样,对于catch子句:
catch_clause: 'catch' catch_arg statement
与
catch_clause: 'catch' catch_arg compound_statement
完整的try / catch块的定义根本不需要更改。不管哪种方式,它都是这样的:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[这里我[whatever]
用来表示可选的内容,而我省略了a的语法,finally_clause
因为我认为它与问题无关。]
即使你不尝试按照所有的类yacc语法定义那里,点可以很容易总结:这一句(以出发try_block
)是一个地方catch
条款会被配对上try
的条款-它仍然准确的无论是否需要大括号,都相同。
重申/总结:括号组一起控制语句通过的catch
S,但这样做不是组catch
Ş自己。这样,那些括号绝对不会决定哪个catch
匹配try
。对于解析器/编译器,无论哪种方式,任务都同样容易(或困难)。尽管如此,@ Tom的答案(以及收到的赞成票的数量)充分说明了这样的变化几乎肯定会使用户感到困惑。
for
零件名称应该像initial
,condition
而step
作为initial
不需要定义一个变量,step
不必是一个增量。