yield-statement:
yield return expression ;
yield break ;
yield 非保留字,僅在緊接 return/break 時有特殊意義,其他情況可作識別項。
finally 區塊內yield return 不可在包含 catch 子句的 try 區塊內任何位置yield break 允許在 try/catch 區塊內IEnumerator<int> GetEnumerator() {
try {
yield return 1; // OK
yield break; // OK
}
finally {
yield return 2; // 錯誤:finally 內不可 yield
yield break; // 錯誤
}
try {
yield return 3; // 錯誤:try-catch 區塊內不可 yield return
yield break; // OK
}
catch {
yield return 4; // 錯誤
yield break; // OK
}
D d = delegate { yield return 5; }; // 錯誤:匿名方法內不可 yield
}
int MyMethod() { yield return 1; } // 錯誤:回傳型別非列舉器/可列舉介面
yield return:評估運算式→隱式轉換至 yield 型別→指派 Current→掛起執行(保存位置/變數,finally 不執行)→狀態→suspended→MoveNext 回傳 true。下次呼叫從掛起處繼續。
yield break:若在 try-finally 內,由內而外執行所有 finally→控制權回呼叫者(MoveNext 或 Dispose)→狀態→after→回傳 false。結束點永不可達。
對 yield return expr:
expr 開頭的賦值狀態 = 語句開頭狀態expr 結束點明確賦值,則語句結束點也明確賦值;否則不public class Stack<T> : IEnumerable<T> {
T[] items; int count;
public IEnumerator<T> GetEnumerator() {
for (int i = count - 1; i >= 0; --i) yield return items[i];
}
}
編譯器轉換為狀態機類別:
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(); }
}
關鍵轉換:區域變數 i 提升為欄位,迭代器邏輯轉為 switch-goto 狀態機。
static IEnumerable<int> FromTo(int from, int to) {
while (from <= to) yield return from++;
}
編譯器產生同時實作 IEnumerable<int>、IEnumerator<int> 的類別:
class __Enumerable1 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator {
int __state, __current, __from, from, to;
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;
}
// MoveNext/Current/Dispose/Reset 實作略...
}
設計亮點:
GetEnumerator 回傳自身,後續回傳拷貝 → 各列舉器狀態獨立Interlocked.CompareExchange 確保執行緒安全from 在區塊內修改,引入 __from 保存初始值供拷貝使用__state==0 時呼叫 MoveNext 拋出 InvalidOperationException,防止未先呼叫 GetEnumerator 直接當列舉器用