search
HomeBackend DevelopmentC#.Net TutorialC# 2.0 Specification (Iterator) (2)

22.4 yield statement

The yield statement is used in an iterator block to produce an enumerator object value, or to indicate the end of iteration.
embedded-statement:(embedded statement)
...
yield-statement(yield statement)
yield-statement:(yield statement)
yield return expression ;
yield break ;
In order to ensure compatibility with existing programs, yield is not a reserved word, and yield has special meaning only immediately before the return or break keyword. In other contexts, it can be used as an identifier.
There are several restrictions on where the yield statement can appear, as described below.
l When the yield statement appears outside the method body, operator body and accessor body, it will cause a compile-time error.
l When the yield statement appears within an anonymous method, it will cause a compile-time error.
l When the yield statement appears in the finally statement of the try statement, it will cause a compile-time error.
l The yield return statement will cause a compile-time error when it appears anywhere in any try statement that contains a catch substatement.
The following examples show some valid and invalid uses of the yield statement.

delegate IEnumerable<int> D();
IEnumerator<int> GetEnumerator() {
try {
yield return 1; // Ok
yield break; // Ok
}
finally {
yield return 2; // 错误, yield 在finally中
yield break; // 错误, yield 在 finally中
}
try {
yield return 3; // 错误, yield return 在try...catch中
yield break; // Ok
}
catch {
yield return 4; // 错误, yield return 在 try...catch中
yield break; // Ok
}
D d = delegate { 
yield return 5; // 错误, yield 在匿名方法中
}; 
}
int MyMethod() {
yield return 1; // 错误, 迭代器块的错误返回类型
}

There must be an implicit conversion (§6.1) from the expression type in the yield return statement to the iterator's yield type (§22.1.3).
The yield return statement is executed as follows.
l The expression given in the statement will be evaluated (evaluated), implicitly converted to the generated type, and assigned to the Current property of the enumerator object.
l The execution of the iterator block will be suspended. If the yield return statement is in one or more try blocks, the associated finally block will not be executed at this time.
l The MoveNext method of the enumerator object returns true to the caller, indicating that the enumerator object successfully advances to the next item.

The next call to the MoveNext method of the enumerator object restarts execution from where the iterator block was suspended.
The yeld break statement is executed as follows.
l If the yield break statement is contained within one or more try blocks with finally blocks, initial control will be transferred to the finally block of the innermost try statement. When control reaches the end of the finally block, control is transferred to the next most recent try statement's finally block. This process will be repeated until all inner finally blocks of try statements have been executed.
l Control is returned to the caller of the iterator block. This may be due to the MoveNext method or Dispose method of the enumerator object.

Since the yield break statement unconditionally transfers control elsewhere, the end point of the yield break statement will never be reached.

22.4.1 Explicit assignment

For the yield return statement stmt in the form of yield return expr

l Like the beginning of stmt, the variable v at the beginning of expr has Explicit assignment status.
l If v is explicitly assigned at the end point of expr, it will also be explicitly assigned at the end point of stmt; otherwise, it will not be explicitly assigned at the end point of stmt

22.5 Implementation example

This section describes possible implementations of iterators in the form of standard C# constructs. The implementation described here is based on the same principles as the Microsoft C# compiler, but it is by no means the mandatory or only possible implementation.
The following Stack class implements the GetEnumerator method using iterators. This iterator enumerates the elements of the stack in order from top to bottom.

using System;
using System.Collections;
using System.Collections.Generic;
class Stack<T>: IEnumerable<T>
{
T[] items;
int count;
public void Push(T item) {
if (items == null) {
items = new T[4];
}
else if (items.Length == count) {
T[] newItems = new T[count * 2];
Array.Copy(items, 0, newItems, 0, count);
items = newItems;
}
items[count++] = item;
}
public T Pop() {
T result = items[--count];
items[count] = T.default;
return result;
}
public IEnumerator<T> GetEnumerator() {
for (int i = count - 1; i >= 0; --i) yield items[i];
}
}

The GetEnumerator method can be converted to an instance of the compiler-generated enumerator class that encapsulates the code in the iterator block, as shown below.

class Stack<T>: IEnumerable<T>
{
...
public IEnumerator<T> GetEnumerator() {
return new __Enumerator1(this);
}
class __Enumerator1: IEnumerator<T>, IEnumerator
{
int __state;
T __current;
Stack<T> __this;
int i;
public __Enumerator1(Stack<T> __this) {
this.__this = __this;
}
public T Current {
get { return __current; }
}
object IEnumerator.Current {
get { return __current; }
}
public bool MoveNext() {
switch (__state) {
case 1: goto __state1;
case 2: goto __state2;
}
i = __this.count - 1;
__loop:
if (i < 0) goto __state2;
__current = __this.items[i];
__state = 1;
return true;
__state1:
--i;
goto __loop;
__state2:
__state = 2;
return false;
}
public void Dispose() {
__state = 2;
}
void IEnumerator.Reset() {
throw new NotSupportedException();
}
}

In the previous conversion, the code inside the iterator block was converted to a state machine and placed in the MoveNext method of the enumerator class. In addition, the local variable i is converted into a field of the enumerator object, so it can persist during the call to MoveNext.
The following example prints a simple multiplication table from integers 1 to 10. In this example, the FromTo method returns an enumerable object and is implemented using an iterator.

using System;
using System.Collections.Generic;
class Test
{
static IEnumerable<int> FromTo(int from, int to) {
while (from <= to) yield return from++;
}
static void Main() {
IEnumerable<int> e = FromTo(1, 10);
foreach (int x in e) {
foreach (int y in e) {
Console.Write("{0,3} ", x * y);
}
Console.WriteLine();
}
}
}

The FromTo method can be converted into an instance of a compiler-generated enumerable class that encapsulates the code in an iterator block, as shown below.

using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
class Test
{
...
static IEnumerable<int> FromTo(int from, int to) {
return new __Enumerable1(from, to);
}
class __Enumerable1:
IEnumerable<int>, IEnumerable,
IEnumerator<int>, IEnumerator
{
int __state;
int __current;
int __from;
int from;
int to;
int i;
public __Enumerable1(int __from, int to) {
this.__from = __from;
this.to = to;
}
public IEnumerator<int> GetEnumerator() {
__Enumerable1 result = this;
if (Interlocked.CompareExchange(ref __state, 1, 0) != 0) {
result = new __Enumerable1(__from, to);
result.__state = 1;
}
result.from = result.__from;
return result;
}
IEnumerator IEnumerable.GetEnumerator() {
return (IEnumerator)GetEnumerator();
}
public int Current {
get { return __current; }
}
object IEnumerator.Current {
get { return __current; }
}
public bool MoveNext() {
switch (__state) {
case 1:
if (from > to) goto case 2;
__current = from++;
__state = 1;
return true;
case 2:
__state = 2;
return false;
default:
throw new InvalidOperationException();
}
}
public void Dispose() {
__state = 2;
}
void IEnumerator.Reset() {
throw new NotSupportedException();
}
}
}

这个可枚举类实现了可枚举接口和枚举器接口,这使得它成为可枚举的或枚举器。当GetEnumerator方法被首次调用时,将返回可枚举对象自身。后续可枚举对象的GetEnumerator调用,如果有的话,都返回可枚举对象的拷贝。因此,每次返回的枚举器都有其自身的状态,改变一个枚举器将不会影响另一个。Interlocked.CompareExchange方法用于确保线程安全操作。

from和to参数被转换为可枚举类的字段。由于from在迭代器块内被修改,所以引入另一个__from字段来保存在每个枚举其中from的初始值。
如果当__state是0时MoveNext被调用,该方法将抛出InvalidOperationException异常。这将防止没有首次调用GetEnumerator,而将可枚举对象作为枚举器而使用的现象发生。

(C# 2.0 Specification 全文完)


以上就是C# 2.0 Specification(迭代器)(二)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
From Web to Desktop: The Versatility of C# .NETFrom Web to Desktop: The Versatility of C# .NETApr 15, 2025 am 12:07 AM

C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.

C# .NET and the Future: Adapting to New TechnologiesC# .NET and the Future: Adapting to New TechnologiesApr 14, 2025 am 12:06 AM

C# and .NET adapt to the needs of emerging technologies through continuous updates and optimizations. 1) C# 9.0 and .NET5 introduce record type and performance optimization. 2) .NETCore enhances cloud native and containerized support. 3) ASP.NETCore integrates with modern web technologies. 4) ML.NET supports machine learning and artificial intelligence. 5) Asynchronous programming and best practices improve performance.

Is C# .NET Right for You? Evaluating its ApplicabilityIs C# .NET Right for You? Evaluating its ApplicabilityApr 13, 2025 am 12:03 AM

C#.NETissuitableforenterprise-levelapplicationswithintheMicrosoftecosystemduetoitsstrongtyping,richlibraries,androbustperformance.However,itmaynotbeidealforcross-platformdevelopmentorwhenrawspeediscritical,wherelanguageslikeRustorGomightbepreferable.

C# Code within .NET: Exploring the Programming ProcessC# Code within .NET: Exploring the Programming ProcessApr 12, 2025 am 12:02 AM

The programming process of C# in .NET includes the following steps: 1) writing C# code, 2) compiling into an intermediate language (IL), and 3) executing by the .NET runtime (CLR). The advantages of C# in .NET are its modern syntax, powerful type system and tight integration with the .NET framework, suitable for various development scenarios from desktop applications to web services.

C# .NET: Exploring Core Concepts and Programming FundamentalsC# .NET: Exploring Core Concepts and Programming FundamentalsApr 10, 2025 am 09:32 AM

C# is a modern, object-oriented programming language developed by Microsoft and as part of the .NET framework. 1.C# supports object-oriented programming (OOP), including encapsulation, inheritance and polymorphism. 2. Asynchronous programming in C# is implemented through async and await keywords to improve application responsiveness. 3. Use LINQ to process data collections concisely. 4. Common errors include null reference exceptions and index out-of-range exceptions. Debugging skills include using a debugger and exception handling. 5. Performance optimization includes using StringBuilder and avoiding unnecessary packing and unboxing.

Testing C# .NET Applications: Unit, Integration, and End-to-End TestingTesting C# .NET Applications: Unit, Integration, and End-to-End TestingApr 09, 2025 am 12:04 AM

Testing strategies for C#.NET applications include unit testing, integration testing, and end-to-end testing. 1. Unit testing ensures that the minimum unit of the code works independently, using the MSTest, NUnit or xUnit framework. 2. Integrated tests verify the functions of multiple units combined, commonly used simulated data and external services. 3. End-to-end testing simulates the user's complete operation process, and Selenium is usually used for automated testing.

Advanced C# .NET Tutorial: Ace Your Next Senior Developer InterviewAdvanced C# .NET Tutorial: Ace Your Next Senior Developer InterviewApr 08, 2025 am 12:06 AM

Interview with C# senior developer requires mastering core knowledge such as asynchronous programming, LINQ, and internal working principles of .NET frameworks. 1. Asynchronous programming simplifies operations through async and await to improve application responsiveness. 2.LINQ operates data in SQL style and pay attention to performance. 3. The CLR of the NET framework manages memory, and garbage collection needs to be used with caution.

C# .NET Interview Questions & Answers: Level Up Your ExpertiseC# .NET Interview Questions & Answers: Level Up Your ExpertiseApr 07, 2025 am 12:01 AM

C#.NET interview questions and answers include basic knowledge, core concepts, and advanced usage. 1) Basic knowledge: C# is an object-oriented language developed by Microsoft and is mainly used in the .NET framework. 2) Core concepts: Delegation and events allow dynamic binding methods, and LINQ provides powerful query functions. 3) Advanced usage: Asynchronous programming improves responsiveness, and expression trees are used for dynamic code construction.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.