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.
Best Answer
In addition to what others have said, it's also possible for an exception to be thrown inside the catch clause. Consider this:
In this example, the
Cleanup()
function never runs, because an exception gets thrown in the catch clause and the next highest up catch in the call stack will catch that. Using a finally block removes this risk, and makes the code cleaner to boot.