IMO, they're included in Java and C# primarily because they already existed in C++. The real question, then, is why is C++ that way. According to The Design and Evolution of C++ (§16.3):
The try
keyword is completely redundant and so are the { }
brackets except where multiple statements are actually used in a try-block or a handler. For example, it would have been trivial to allow:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
However, I found this so difficult to explain that the redundancy was introduced to save support personnel from confused users.
Edit: As to why this would be confusing, I think one has only to look at the incorrect assertions in @Tom Jeffery's answer (and, especially, the number of up-votes it has received) to realize that there would be a problem. To the parser, this is really no different from matching else
s with if
s -- lacking braces to force other grouping, all catch
clauses would match up with the most recent throw
. For those misbegotten languags that include it, finally
clauses would do the same. From the viewpoint of the parser, this is hardly enough different from the current situation to notice -- in particular, as the grammars stand now, there's really nothing to group the catch
clauses together -- the brackets group the statements controlled by the catch
clauses, not the catch clauses themselves.
From the viewpoint of writing a parser, the difference is almost too tiny to notice. If we start with something like this:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
Then the difference would be between:
try_clause: 'try' statement
and:
try_clause: 'try' compound_statement
Likewise, for catch clauses:
catch_clause: 'catch' catch_arg statement
vs.
catch_clause: 'catch' catch_arg compound_statement
The definition of a complete try/catch block would not need to change at all though. Either way it would be something like:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[Here I'm using [whatever]
to indicate something optional, and I'm leaving out the syntax for a finally_clause
since I don't think it has any bearing on the question.]
Even if you don't try to follow all the Yacc-like grammar definition there, the point can be summarized fairly easily: that last statement (starting with try_block
) is the one where catch
clauses get matched up with try
clauses -- and it remains exactly the same whether the braces are required or not.
To reiterate/summarize: the braces group together the statements controlled by the catch
s, but do not group the catch
s themselves. As such, those braces have absolutely no effect upon deciding which catch
goes with which try
. For the parser/compiler the task is equally easy (or difficult) either way. Despite this, @Tom's answer (and the number of up-votes it's received) provides ample demonstration of the fact that such a change would almost certainly confuse users.
for
the parts should be named something likeinitial
,condition
andstep
asinitial
need not define a variable andstep
need not be an increment. – Joachim Sauer Nov 3 '11 at 13:58if
is always a single statement, and multiple statements enclosed by braces comprise a single statement. But I'm one of those who always put the braces in anyway, so... – detly Nov 4 '11 at 3:24throw
andreturn
, and like @detly said, if you consider the braces as a single group of statements, I don't find it inconsistent either. I've never understood what these "lots of coding errors" mentioned by people are. People need to start paying attention to what they do, use proper indention and have unit tests :P never had a problem with this... – Svish Nov 4 '11 at 7:18