dotnet / dotnet/csharplang

[Proposal]: Expression blocks

Open
#9,243 0 comments 0 reactions 1 assignee Claimed by @cston View on GitHub
Proposal Proposal champion
Dominant language
C#
Stars
12.7k
Forks
1.1k
Avg merge
11h 1m
Merged PRs (30d)
3

Description

# Expression blocks

## Summary

* Specification: Link to a filled out [proposal template](../../proposals/proposal-template.md). If not yet available, link to the PR adding the specification.
* Discussion: https://github.com/dotnet/csharplang/discussions/9242

Allow a block of statements with a trailing expression as an expression.

### Syntax
```antlr
expression
: non_assignment_expression
| assignment
;

non_assignment_expression
: conditional_expression
| lambda_expression
| query_expression
| block_expression
;

block_expression
: '{' statement+ expression '}'
;
```

Examples:
```C#
x = { ; 1 }; // expression block
x = { {} 2 }; // expression block

y = new MyCollection[]
{
{ F(), 3 }, // collection initializer
{ F(); 4 }, // expression block
};

f = () => { F(); G(); }; // block body
f = () => { F(); G() }; // expression body
```

### Execution
An expression block is executed by transferring control to the first statement.
When and if control reaches the end of a statement, control is transferred to the next statement.
When and if control reaches the end of the last statement, the trailing expression is evaluated and the result left on the evaluation stack.

The evaluation stack may not be empty at the beginning of the expression block so control cannot enter the block other than at the first statement.
Control cannot leave the block other than after the trailing expression unless an exception is thrown executing the statements or the expression.

### Restrictions
`return`, `yield break`, `yield return` are not allowed in the expression block statements.

`break` and `continue` may be used only in nested loops or `switch` statements.

`goto` may be used to jump to other statements within the expression block but not to statements outside the block.

`out` variable declarations in the statements or expression are scoped to the expression block.

`using expr;` may be used in the statements. The implicit `try` / `finally` surrounds the remaining statements and the trailing expression so `Dispose()` is invoked after evaluating the trailing expression.

Expression trees cannot contain block expressions.

## Design Meetings/Alternatives

[Proposal: Sequence Expressions #377](https://github.com/dotnet/csharplang/issues/377)
[LDM 2020-01-22](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-01-22.md#block-expressions)
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-26.md#discriminated-unions
https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-08-28.md#block-bodied-switch-expression-arms

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.