Skip to content

Commit 881c043

Browse files
RexJaeschkeBillWagnerNeal Gafterjskeet
authored
C# v7.x: Throw Expressions (#65)
* Update expressions.md * build fixes * Minor changes to bring this in line with the spec style and organization. * Expression bodied member can be a throw expression. * Add throw expression as a category into which an expression may be classified. * Fix section number. * fix merge error. * add column end marker * still rendering * add one more escape it appears that once any vertical bar is escaped in a table, they all must be. * Add throw expressions to precedence table * Move throw expression to a new top-level section after null coalescing operator * Fix typo * Update reference * Update link to new section Co-authored-by: Bill Wagner <[email protected]> Co-authored-by: Bill Wagner <[email protected]> Co-authored-by: Neal Gafter <[email protected]> Co-authored-by: Jon Skeet <[email protected]>
1 parent 2803b76 commit 881c043

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

standard/conversions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ The following conversions are classified as implicit conversions:
5959
- Null literal conversions
6060
- Implicit nullable conversions
6161
- Lifted user-defined implicit conversions
62+
- Implicit throw conversion
6263
6364
Implicit conversions can occur in a variety of situations, including function member invocations ([§11.6.6](expressions.md#1166-function-member-invocation)), cast expressions ([§11.8.7](expressions.md#1187-cast-expressions)), and assignments ([§11.18](expressions.md#1118-assignment-operators)).
6465
@@ -301,6 +302,10 @@ A user-defined implicit conversion consists of an optional standard implicit con
301302
302303
Anonymous functions and method groups do not have types in and of themselves, but they may be implicitly converted to delegate types. Additionally, some lambda expressions may be implicitly converted to expression tree types. Anonymous function conversions are described in more detail in [§10.7](conversions.md#107-anonymous-function-conversions) and method group conversions in [§10.8](conversions.md#108-method-group-conversions).
303304
305+
### 10.2.15 Implicit throw conversions
306+
307+
While throw expressions do not have a type, they may be implicitly converted to any type.
308+
304309
## 10.3 Explicit conversions
305310
306311
### 10.3.1 General

standard/expressions.md

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ For expressions which occur as subexpressions of larger expressions, with the no
2424
- A type. An expression with this classification can only appear as the left-hand side of a *member_access* ([§11.7.6](expressions.md#1176-member-access)). In any other context, an expression classified as a type causes a compile-time error.
2525
- A method group, which is a set of overloaded methods resulting from a member lookup ([§11.5](expressions.md#115-member-lookup)). A method group may have an associated instance expression and an associated type argument list. When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§11.7.12](expressions.md#11712-this-access)). A method group is permitted in an *invocation_expression* ([§11.7.8](expressions.md#1178-invocation-expressions)) or a *delegate_creation_expression* ([§11.7.15.6](expressions.md#117156-delegate-creation-expressions)), and can be implicitly converted to a compatible delegate type ([§10.8](conversions.md#108-method-group-conversions)). In any other context, an expression classified as a method group causes a compile-time error.
2626
- An event access. Every event access has an associated type, namely the type of the event. Furthermore, an event access may have an associated instance expression. An event access may appear as the left-hand operand of the `+=` and `-=` operators ([§11.18.4](expressions.md#11184-event-assignment)). In any other context, an expression classified as an event access causes a compile-time error. When an accessor of an instance event access is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§11.7.12](expressions.md#11712-this-access)).
27+
- A throw expression, which may be used is several contexts to throw an exception in an expression. A throw expression may be converted by an implicit conversion to any type.
2728

2829
A property access or indexer access is always reclassified as a value by performing an invocation of the *get_accessor* or the *set_accessor*. The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the *set_accessor* is invoked to assign a new value ([§11.18.2](expressions.md#11182-simple-assignment)). Otherwise, the *get_accessor* is invoked to obtain the current value ([§11.2.2](expressions.md#1122-values-of-expressions)).
2930

@@ -139,23 +140,23 @@ The precedence of an operator is established by the definition of its associated
139140
<!-- markdownlint-enable MD028 -->
140141
> *Note*: The following table summarizes all operators in order of precedence from highest to lowest:
141142
>
142-
> | **Subclause** | **Category** | **Operators**
143-
> | ----------------- | ------------------------------- | -------------------------------------------------------
144-
> | [§11.7](expressions.md#117-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `new` `typeof` `default` `checked` `unchecked` `delegate`
145-
> | [§11.8](expressions.md#118-unary-operators) | Unary | `+` `-` `!` `~` `++x` `--x` `(T)x` `await x`
146-
> | [§11.9](expressions.md#119-arithmetic-operators) | Multiplicative | `*` `/` `%`
147-
> | [§11.9](expressions.md#119-arithmetic-operators) | Additive | `+` `-`
148-
> | [§11.10](expressions.md#1110-shift-operators) | Shift | `<<` `>>`
149-
> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as`
150-
> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Equality | `==` `!=`
151-
> | [§11.12](expressions.md#1112-logical-operators) | Logical AND | `&`
152-
> | [§11.12](expressions.md#1112-logical-operators) | Logical XOR | `^`
153-
> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `|`
154-
> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&`
155-
> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `||`
156-
> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??`
157-
> | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:`
158-
> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>`
143+
> | **Subclause** | **Category** | **Operators** |
144+
> | ----------------- | ------------------------------- | -------------------------------------------------------|
145+
> | [§11.7](expressions.md#117-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `new` `typeof` `default` `checked` `unchecked` `delegate` |
146+
> | [§11.8](expressions.md#118-unary-operators) | Unary | `+` `-` `!` `~` `++x` `--x` `(T)x` `await x` |
147+
> | [§11.9](expressions.md#119-arithmetic-operators) | Multiplicative | `*` `/` `%` |
148+
> | [§11.9](expressions.md#119-arithmetic-operators) | Additive | `+` `-` |
149+
> | [§11.10](expressions.md#1110-shift-operators) | Shift | `<<` `>>` |
150+
> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` |
151+
> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Equality | `==` `!=` |
152+
> | [§11.12](expressions.md#1112-logical-operators) | Logical AND | `&` |
153+
> | [§11.12](expressions.md#1112-logical-operators) | Logical XOR | `^` |
154+
> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` |
155+
> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` |
156+
> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` |
157+
> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and §throw-expression-operator-new-clause | Null coalescing and throw expression | `??` `throw x` |
158+
> | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` |
159+
> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` |
159160
>
160161
> *end note*
161162
@@ -4218,6 +4219,7 @@ The `??` operator is called the null coalescing operator.
42184219
null_coalescing_expression
42194220
: conditional_or_expression
42204221
| conditional_or_expression '??' null_coalescing_expression
4222+
| throw_expression
42214223
;
42224224
```
42234225

@@ -4238,6 +4240,24 @@ The type of the expression `a ?? b` depends on which implicit conversions are
42384240

42394241
Otherwise, `a` and `b` are incompatible, and `a` compile-time error occurs.
42404242

4243+
## §throw-expression-operator-new-clause The throw expression operator
4244+
4245+
```ANTLR
4246+
throw_expression
4247+
: 'throw' null_coalescing_expression
4248+
;
4249+
```
4250+
4251+
A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)).
4252+
4253+
A *throw_expression* has no type. A *throw_expression* is convertible to every type by an *implicit throw conversion*.
4254+
4255+
A *throw expression* shall only occur in the following syntactic contexts:
4256+
4257+
- As the second or third operand of a ternary conditional operator (`?:`).
4258+
- As the second operand of a null coalescing operator (`??`).
4259+
- As the body of an expression-bodied lambda or member.
4260+
42414261
## 11.15 Conditional operator
42424262

42434263
The `?:` operator is called the conditional operator. It is at times also called the ternary operator.

standard/variables.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,15 @@ For a *lambda_expression* or *anonymous_method_expression* *expr* with a body (e
802802
>
803803
> *end example*
804804
805+
#### §throw-expression-new-clause Throw expressions
806+
807+
For an expression *expr* of the form:
808+
809+
`throw` *thrown_expr*
810+
811+
- The definite assignment state of *v* before *thrown_expr* is the same as the state of *v* before *expr*.
812+
- The definite assignment state of *v* after *expr* is "definitely assigned".
813+
805814
#### 9.4.4.32 Rules for variables in local functions
806815
807816
Local functions are analyzed in the context of their parent method. There are two control flow paths that matter for local functions: function calls and delegate conversions.

0 commit comments

Comments
 (0)