You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: standard/expressions.md
+103-2Lines changed: 103 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2070,6 +2070,7 @@ member_declarator
2070
2070
:simple_name
2071
2071
|member_access
2072
2072
|base_access
2073
+
|null_conditional_member_access
2073
2074
|identifier'='expression
2074
2075
;
2075
2076
```
@@ -2118,7 +2119,7 @@ Within the same program, two anonymous object initializers that specify a sequen
2118
2119
2119
2120
The `Equals` and `GetHashcode` methodsonanonymoustypesoverridethemethodsinheritedfrom `object`, andaredefinedintermsofthe `Equals` and `GetHashcode` oftheproperties, sothattwoinstancesofthesameanonymoustypeareequalifandonlyifalltheirpropertiesareequal.
@@ -2380,6 +2381,7 @@ The `+`, `-`, `!`, `~`, `++`, `--`, cast, and `await` operators are called the u
2380
2381
```ANTLR
2381
2382
unary_expression
2382
2383
: primary_expression
2384
+
| null_conditional_expression
2383
2385
| '+' unary_expression
2384
2386
| '-' unary_expression
2385
2387
| '!' unary_expression
@@ -2393,6 +2395,106 @@ unary_expression
2393
2395
2394
2396
If the operand of a *unary_expression* has the compile-time type `dynamic`, it is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)). In this case, the compile-time type of the *unary_expression* is `dynamic`, and the resolution described below will take place at run-time using the run-time type of the operand.
The null-conditional operator applies a list of operations to its operand only if that operand is non-`null`. Otherwise the result of applying the operator is `null`.
The list of operations can include member access and element access operations (which may themselves be null-conditional), as well as invocation.
2419
+
> *Example* : The expression `a.b?[0]?.c()` is a *null_conditional_expression* with a *primary_expression*`a.b` and *null_conditional_operations*`?[0]` (null-conditional element access), `?.c` (null-conditional member access) and `()` (invocation). *end example*
2420
+
2421
+
For a *null_conditional_expression*`E` with a *primary_expression*`P`, let `E₀` be the expression obtained by textually removing the leading `?` from each of the *null_conditional_operations* of `E` that have one. Conceptually, `E₀` is the expression that will be evaluated if none of the null checks represented by the `?`s do find a `null`.
2422
+
2423
+
Also, let `E₁` be the expression obtained by textually removing the leading `?` from just the first of the *null_conditional_operations* in `E`. This may lead to a *primary-expression* (if there was just one `?`) or to another *null_conditional_expression*.
2424
+
2425
+
> *Example* : If `E` is the expression `a.b?[0]?.c()`, then `E₀` is the expression `a.b[0].c()` and `E₁` is the expression `a.b[0]?.c()`. *end example*
2426
+
2427
+
If `E₀` is classified as nothing, then `E` is classified as nothing. Otherwise `E` is classified as a value.
2428
+
`E₀` and `E₁` are used to determine the meaning of `E`:
2429
+
- If `E` occurs as a *statement_expression* the meaning of `E` is the same as the statement
2430
+
```csharp
2431
+
if ((object)P!=null) E₁;
2432
+
```
2433
+
except that `P` is evaluated only once.
2434
+
- Otherwise, if `E₀` is classified as nothing a compile-time error occurs.
2435
+
- Otherwise, let `T₀` be the type of `E₀`.
2436
+
- If `T₀` is a type parameter that is not known to be a reference type or a non-nullable value type, a compile-time error occurs.
2437
+
- If `T₀` is a non-nullable value type, then the type of `E` is `T₀?`, and the meaning of `E` is the same as
2438
+
```csharp
2439
+
((object)P==null) ? (T₀?)null:E₁
2440
+
```
2441
+
exceptthat `P` isevaluatedonlyonce.
2442
+
- Otherwisethetypeof `E` is `T₀`, andthemeaningof `E` isthesameas
2443
+
```csharp
2444
+
((object)P==null) ?null:E₁
2445
+
```
2446
+
exceptthat `P` isevaluatedonlyonce.
2447
+
2448
+
If `E₁` isitselfa *null_conditional_expression*, thentheserulesareappliedagain, nestingthetestsfor `null` until there are no further `?`'s, and the expression has been reduced all the way down to the primary-expression `E₀`.
2449
+
2450
+
> *Example* : If the expression `a.b?[0]?.c()` occursasastatement-expression, asinthestatement:
2451
+
> ```csharp
2452
+
>a.b?[0]?.c();
2453
+
> ```
2454
+
>itsmeaningisequivalentto:
2455
+
> ```csharp
2456
+
>if (a.b!=null) a.b[0]?.c();
2457
+
> ```
2458
+
>whichagainisequivalentto:
2459
+
> ```csharp
2460
+
>if (a.b!=null) if (a.b[0] !=null) a.b[0].c();
2461
+
> ```
2462
+
>exceptthat `a.b` and `a.b[0]` areevaluatedonlyonce.
This is a special case of the grammar for *null_conditional_expression* above. The production for *member_declarator* in [§12.7.11.7](expressions.md#127117-anonymous-object-creation-expressions) then includes only *null_conditional_member_access*.
2485
+
2486
+
#### §null-conditional-operator-statement Null-conditional expressions as statement expressions
2487
+
2488
+
A null-conditional expression is only allowed as a *statement_expression* ([§13.7](statements.md#137-expression-statements)) if it ends with an invocation. Grammatically, this requirement can be expressed as:
This is a special case of the grammar for *null_conditional_expression* above. The production for *statement_expression* in [§13.7](statements.md#137-expression-statements) then includes only *null_conditional_invocation_expression*.
2497
+
2396
2498
### 12.8.2 Unary plus operator
2397
2499
2398
2500
For an operation of the form `+x`, unary operator overload resolution ([§12.4.4](expressions.md#1244-unary-operator-overload-resolution)) is applied to select a specific operator implementation. The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. The predefined unary plus operators are:
@@ -2556,7 +2658,6 @@ await_expression
2556
2658
An *await_expression* is only allowed in the body of an async function ([§15.15](classes.md#1515-async-functions)). Within the nearest enclosing async function, an *await_expression* shall not occur in these places:
2557
2659
2558
2660
- Inside a nested (non-async) anonymous function
2559
-
- In a `catch` or `finally` block of a *try_statement*
2560
2661
- Inside the block of a *lock_statement*
2561
2662
- In an anonymous function conversion to an expression tree type ([§11.7.3](conversions.md#1173-evaluation-of-anonymous-function-conversions-to-expression-tree-types))
0 commit comments