Skip to content

Commit

Permalink
C# 6.0 feature: Exception Filters (#2)
Browse files Browse the repository at this point in the history
* feature exception filters

Add "when" as a contextual keyword.
Update grammar for exception filters
Add description of exception filters.

* respond to suggestions

* restore grammar updates

* Apply suggestions from code review

Co-authored-by: Neal Gafter <[email protected]>

* Update recommended at meeting

Update the grammar and the description of the `try` statement.  See dotnet/csharpstandard#2 (comment)

Co-authored-by: Neal Gafter <[email protected]>
  • Loading branch information
brendasmith8 and gafter committed Oct 21, 2021
1 parent 1006068 commit 191820f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 20 deletions.
2 changes: 1 addition & 1 deletion standard/lexical-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ contextual_keyword
| 'get' | 'global' | 'group' | 'into' | 'join'
| 'let' | 'nameof' | 'on' | 'orderby' | 'partial'
| 'remove' | 'select' | 'set' | 'value' | 'var'
| 'where' | 'yield'
| 'when' | 'where' | 'yield'
;
```

Expand Down
42 changes: 23 additions & 19 deletions standard/statements.md
Original file line number Diff line number Diff line change
Expand Up @@ -1086,41 +1086,44 @@ The `try` statement provides a mechanism for catching exceptions that occur duri
```ANTLR
try_statement
: 'try' block catch_clause+
| 'try' block finally_clause
| 'try' block catch_clause+ finally_clause
: 'try' block catch_clauses
| 'try' block catch_clauses* finally_clause
;
catch_clause
: 'catch' exception_specifier? block
catch_clauses
: specific_catch_clause+
| specific_catch_clause* general_catch_clause
;
specific_catch_clause
: 'catch' exception_specifier exception_filter? block
: 'catch' exception_filter block
;
exception_specifier
: '(' type identifier? ')'
;
exception_filter
: 'when' '(' boolean_expression ')'
;
general_catch_clause
: 'catch' block
;
finally_clause
: 'finally' block
;
```
There are three possible forms of `try` statements:
- A `try` block followed by one or more `catch` blocks.
- A `try` block followed by a `finally` block.
- A `try` block followed by one or more `catch` blocks followed by a `finally` block.
A *try_statement* consists of the keyword `try` followed by a *block*, then zero or more *catch_clauses*, then an optional *finally_clause*. There must be at least one *catch_clause* or a *finally_clause*.
When a `catch` clause specifies a *type*, the type shall be `System.Exception` or a type that derives from `System.Exception`. When a `catch` clause specifies a *type_parameter* it shall be a type parameter type whose effective base class is or derives from `System.Exception`.
In an *exception_specifier* the *type*, or its effective base class if it is a *type_parameter*, shall be `System.Exception` or a type that derives from it.
When a `catch` clause specifies both a *class_type* and an *identifier*, an ***exception variable*** of the given name and type is declared. The exception variable corresponds to a local variable with a scope that extends over the `catch` block. During execution of the `catch` block, the exception variable represents the exception currently being handled. For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.
When a `catch` clause specifies both a *class_type* and an *identifier*, an ***exception variable*** of the given name and type is declared. The exception variable corresponds to a local variable with a scope that extends over the `catch` block. During execution of the *exception_filter* and `catch` block, the exception variable represents the exception currently being handled. For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.
Unless a `catch` clause includes an exception variable name, it is impossible to access the exception object in the `catch` block.
Unless a `catch` clause includes an exception variable name, it is impossible to access the exception object in the filter and `catch` block.
A `catch` clause that specifies neither an exception type nor an exception variable name is called a general `catch` clause. A `try` statement can only have one general `catch` clause, and, if one is present, it shall be the last `catch` clause.
> *Note*: Some programming languages might support exceptions that are not representable as an object derived from `System.Exception`, although such exceptions could never be generated by C# code. A general `catch` clause might be used to catch such exceptions. Thus, a general `catch` clause is semantically different from one that specifies the type `System.Exception`, in that the former might also catch exceptions from other languages. *end note*
In order to locate a handler for an exception, `catch` clauses are examined in lexical order. A compile-time error occurs if a `catch` clause specifies a type that is the same as, or is derived from, a type that was specified in an earlier `catch` clause for the same try.
In order to locate a handler for an exception, `catch` clauses are examined in lexical order. If a `catch` clause specifies a type but no exception filter, it is a compile-time error for a later `catch` clause of the same `try` statement to specify a type that is the same as, or is derived from, that type.
> *Note*: Without this restriction, it would be possible to write unreachable `catch` clauses. *end note*
Expand Down Expand Up @@ -1177,9 +1180,10 @@ A `try` statement is executed as follows:
- If the `try` statement has a `finally` block, the `finally` block is executed.
- Control is transferred to the end point of the `try` statement.
- If an exception is propagated to the `try` statement during execution of the `try` block:
- The `catch` clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. The first `catch` clause that specifies the exception type or a base type of the exception type is considered a match. A general `catch` clause is considered a match for any exception type. If a matching `catch` clause is located:
- The `catch` clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Each `catch` clause that does not specify a type, or specifies the exception type or a base type of the exception type, is considered a match. If a matching `catch` clause is located:
- If the matching `catch` clause declares an exception variable, the exception object is assigned to the exception variable.
- Control is transferred to the matching `catch` block.
- If the `catch` clause declares an exception filter, the filter is evaluated. If it evaluates to `false`, the search continues through any subsequent `catch` clauses for a suitable handler.
- Otherwise control is transferred to the corresponding `catch` block.
- When and if control reaches the end point of the `catch` block:
- If the `try` statement has a `finally` block, the `finally` block is executed.
- Control is transferred to the end point of the `try` statement.
Expand Down

0 comments on commit 191820f

Please sign in to comment.