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/classes.md
+16-14Lines changed: 16 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -5471,29 +5471,29 @@ This allows the context to keep track of how many `void`-returning async functio
5471
5471
5472
5472
### 15.15.1 General
5473
5473
5474
-
A function member ([§12.6](expressions.md#126-function-members)) or local function ([§13.6.4](statements.md#1364-local-function-declarations)) implemented using an iterator block ([§13.3](statements.md#133-blocks)) is called an ***iterator***. An iterator block may be used as the body of a function member as long as the return type of the corresponding function member is one of the enumerator interfaces ([§15.15.2](classes.md#15152-enumerator-interfaces)) or one of the enumerable interfaces ([§15.15.3](classes.md#15153-enumerable-interfaces)).
5474
+
A function member ([§12.6](expressions.md#126-function-members)) or local function ([§13.6.4](statements.md#1364-local-function-declarations)) implemented using an iterator block ([§13.3](statements.md#133-blocks)) is called an ***iterator***. An iterator block may be used as the body of a function as long as the return type of the corresponding function is one of the enumerator interfaces ([§15.15.2](classes.md#15152-enumerator-interfaces)) or one of the enumerable interfaces ([§15.15.3](classes.md#15153-enumerable-interfaces)).
5475
5475
5476
-
An async function ([§15.14](classes.md#1514-async-functions)) implemented using an iterator block ([§13.3](statements.md#133-blocks)) is called an ***asynchronous iterator***. An asynchronous iterator block may be used as the body of a function member as long as the return type of the corresponding function member is the asynchronous enumerator interfaces ([§15.15.2](classes.md#15152-enumerator-interfaces)) or the asynchronous enumerable interfaces ([§15.15.3](classes.md#15153-enumerable-interfaces)).
5476
+
An async function ([§15.14](classes.md#1514-async-functions)) implemented using an iterator block ([§13.3](statements.md#133-blocks)) is called an ***asynchronous iterator***. An asynchronous iterator block may be used as the body of a function as long as the return type of the corresponding function is the asynchronous enumerator interfaces ([§15.15.2](classes.md#15152-enumerator-interfaces)) or the asynchronous enumerable interfaces ([§15.15.3](classes.md#15153-enumerable-interfaces)).
5477
5477
5478
5478
An iterator block may occur as a *method_body*, *operator_body* or *accessor_body*, whereas events, instance constructors, static constructors and finalizer shall not be implemented as synchronous or asynchronous iterators.
5479
5479
5480
-
When a function member or local function is implemented using an iterator block, it is a compile-time error for the parameter list of the function member to specify any `in`, `out`, or `ref` parameters, or an parameter of a `ref struct` type.
5480
+
When a function is implemented using an iterator block, it is a compile-time error for the parameter list of the function to specify any `in`, `out`, or `ref` parameters, or a parameter of a `ref struct` type.
5481
5481
5482
5482
An asynchronous iterator can support cancellation of the asynchronous operation. One parameter must be of the type `System.Threading.Tasks.CancellationToken` and be marked with the `System.Runtime.CompilerServices.EnumeratorCancellation` attribute (§enumerator-cancellation). When an asynchronous iterator has such a parameter, that `CancellationToken` is passed to `GetAsyncEnumerator`, and the enumerator's `MoveNextAsync` method.
5483
5483
5484
5484
### 15.15.2 Enumerator interfaces
5485
5485
5486
-
The ***enumerator interfaces*** are the non-generic interface `System.Collections.IEnumerator` and all instantiations of the generic interfaces`System.Collections.Generic.IEnumerator<T>`.
5486
+
The ***enumerator interfaces*** are the non-generic interface `System.Collections.IEnumerator` and the generic interface`System.Collections.Generic.IEnumerator<T>`.
5487
5487
5488
-
The ***asynchronous enumerator interfaces***are all instantiations of the generic interface `System.Collections.Generic.IAsyncEnumerator<T>`.
5488
+
The ***asynchronous enumerator interface***is the generic interface `System.Collections.Generic.IAsyncEnumerator<T>`.
5489
5489
5490
5490
For the sake of brevity, in this subclause and its siblings these interfaces are referenced as `IEnumerator`, `IEnumerator<T>`, and `IAsyncEnumerator<T>`, respectively.
5491
5491
5492
5492
### 15.15.3 Enumerable interfaces
5493
5493
5494
-
The ***enumerable interfaces*** are the non-generic interface `System.Collections.IEnumerable` and all instantiations of the generic interfaces `System.Collections.Generic.IEnumerable<T>`.
5494
+
The ***enumerable interfaces*** are the non-generic interface `System.Collections.IEnumerable` and the generic interfaces `System.Collections.Generic.IEnumerable<T>`.
5495
5495
5496
-
The ***asynchronous enumerable interfaces***are all instantiations of the generic interface `System.Collections.Generic.IAsyncEnumerable<T>`.
5496
+
The ***asynchronous enumerable interface***is the generic interface `System.Collections.Generic.IAsyncEnumerable<T>`.
5497
5497
5498
5498
For the sake of brevity, in this subclause and its siblings these interfaces are referenced as `IEnumerable`, `IEnumerable<T>`, and `IAsyncEnumerable<T>`, respectively.
5499
5499
@@ -5508,13 +5508,13 @@ An iterator produces a sequence of values, all of the same type. This type is ca
5508
5508
5509
5509
#### 15.15.5.1 General
5510
5510
5511
-
When a function member or local function returning an enumerator interface type is implemented using an iterator block, invoking the function does not immediately execute the code in the iterator block. Instead, an ***enumerator object*** is created and returned. This object encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object’s `MoveNext` or `MoveNextAsync` method is invoked. An enumerator object has the following characteristics:
5511
+
When a function member or local function returning an enumerator interface type or an asynchronous enumerator interface type is implemented using an iterator block, invoking the function does not immediately execute the code in the iterator block. Instead, an ***enumerator object*** is created and returned. This object encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object’s `MoveNext` or `MoveNextAsync` method is invoked. An enumerator object has the following characteristics:
5512
5512
5513
5513
- It implements `System.IDisposable`, `IEnumerator` and `IEnumerator<T>`, or `System.IAsyncDisposable` and `IAsyncEnumerator<T>`, where `T` is the yield type of the iterator.
5514
-
- It is initialized with a copy of the argument values (if any) and instance value passed to the function member.
5514
+
- It is initialized with a copy of the argument values (if any) and instance value passed to the function.
5515
5515
- It has four potential states, **before**, **running**, **suspended**, and **after**, and is initially in the **before** state.
5516
5516
5517
-
An enumerator object is typically an instance of a compiler-generated enumerator class that encapsulates the code in the iterator block and implements the enumerator interfaces, but other methods of implementation are possible. If an enumerator class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use ([§6.4.3](lexical-structure.md#643-identifiers)).
5517
+
An enumerator object is typically an instance of a compiler-generated enumerator class that encapsulates the code in the iterator block and implements the enumerator interfaces, but other methods of implementation are possible. If an enumerator class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function, it will have private accessibility, and it will have a name reserved for compiler use ([§6.4.3](lexical-structure.md#643-identifiers)).
5518
5518
5519
5519
An enumerator object may implement more interfaces than those specified above.
5520
5520
@@ -5552,6 +5552,8 @@ The precise action performed by `MoveNext` or `MoveNextAsync` depends on the sta
5552
5552
5553
5553
When `MoveNext` executes the iterator block, execution can be interrupted in four ways: By a `yield return` statement, by a `yield break` statement, by encountering the end of the iterator block, and by an exception being thrown and propagated out of the iterator block.
5554
5554
5555
+
> *Note*: `MoveNextAsync` can be suspended with an `await` expression
5556
+
5555
5557
- When a `yield return` statement is encountered ([§9.4.4.20](variables.md#94420-yield-statements)):
5556
5558
- The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the `Current` property of the enumerator object.
5557
5559
- Execution of the iterator body is suspended. The values of all local variables and parameters (including `this`) are saved, as is the location of this `yield return` statement. If the `yield return` statement is within one or more `try` blocks, the associated finally blocks are *not* executed at this time.
@@ -5595,18 +5597,18 @@ The `Dispose` or `DisposeAsync` method is used to clean up the iteration by brin
5595
5597
5596
5598
#### 15.15.6.1 General
5597
5599
5598
-
When a function member or local function returning an enumerable interface type is implemented using an iterator block, invoking the function member does not immediately execute the code in the iterator block. Instead, an ***enumerable object*** is created and returned.
5600
+
When a function member or local function returning an enumerable interface type or an async enumerable interface type is implemented using an iterator block, invoking the function does not immediately execute the code in the iterator block. Instead, an ***enumerable object*** is created and returned.
5599
5601
5600
5602
The enumerable object’s `GetEnumerator` or `GetAsyncEnumerator` method returns an enumerator object that encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object’s `MoveNext` or `MoveNextAsync` method is invoked. An enumerable object has the following characteristics:
5601
5603
5602
5604
- It implements `IEnumerable` and `IEnumerable<T>` or `IAsyncEnumerable<T>`, where `T` is the yield type of the iterator.
5603
-
- It is initialized with a copy of the argument values (if any) and instance value passed to the function member.
5605
+
- It is initialized with a copy of the argument values (if any) and instance value passed to the function.
5604
5606
5605
-
An enumerable object is typically an instance of a compiler-generated enumerable class that encapsulates the code in the iterator block and implements the enumerable interfaces, but other methods of implementation are possible. If an enumerable class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use ([§6.4.3](lexical-structure.md#643-identifiers)).
5607
+
An enumerable object is typically an instance of a compiler-generated enumerable class that encapsulates the code in the iterator block and implements the enumerable interfaces, but other methods of implementation are possible. If an enumerable class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function, it will have private accessibility, and it will have a name reserved for compiler use ([§6.4.3](lexical-structure.md#643-identifiers)).
5606
5608
5607
5609
An enumerable object may implement more interfaces than those specified above.
5608
5610
5609
-
> *Note*: For example, an enumerable object may also implement `IEnumerator` and `IEnumerator<T>`, enabling it to serve as both an enumerable and an enumerator. Typically, such an implementation would return its own instance (to save allocations) from the first call to `GetEnumerator`. Subsequent invocations of `GetEnumerator`, if any, would return a new class instance, typically of the same class, so that calls to different enumerator instances will not affect each other. It cannot return the same instance even if the previous enumerator has already enumerated past the end of the sequence, since all future calls to an exhausted enumerator must throw exceptions. *end note*
5611
+
> *Note*: For example, an enumerable object may also implement `IEnumerator` and `IEnumerator<T>`, enabling it to serve as both an enumerable and an enumerator. Typically, such an implementation would return its own instance (to save allocations) from the first call to `GetEnumerator`. Subsequent invocations of `GetEnumerator`, if any, would return a new class instance, typically of the same class, so that calls to different enumerator instances will not affect each other. *end note*
5610
5612
5611
5613
#### 15.15.6.2 The GetEnumerator or GetAsyncEnumerator method
0 commit comments