From 191820fde4c7faa665ef577df0dfbc272ec4cd96 Mon Sep 17 00:00:00 2001 From: brendasmith8 Date: Thu, 21 Oct 2021 16:06:24 -0400 Subject: [PATCH] C# 6.0 feature: Exception Filters (#2) * 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 * Update recommended at meeting Update the grammar and the description of the `try` statement. See https://github.com/dotnet/csharpstandard/pull/2#issuecomment-948018076 Co-authored-by: Neal Gafter --- standard/lexical-structure.md | 2 +- standard/statements.md | 42 +++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 9508d9c..fe64d0e 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -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' ; ``` diff --git a/standard/statements.md b/standard/statements.md index 53c99ee..d56a898 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -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* @@ -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.