C#中调用返回IEnumerator的yield方法为何未立即执行方法体?
Understanding Iterator Method Behavior in Your GameMoves Class
Hey there! Let's break down exactly what's happening with your Cross() method call in the constructor—this is a super common gotcha with C# iterator methods, so you're not alone in wondering about this.
First, the Core Difference: Iterator Methods vs. Regular Methods
The key here is recognizing that Cross() is an iterator method (it returns IEnumerator or IEnumerator<T> and uses yield return/yield break somewhere in its body), while your I() method is a regular method.
- For a regular method like
I(): When you call it (e.g.,i = I();), the runtime immediately executes the entire method body and returns the value specified by thereturnstatement. No delays, no state machines—just straight execution. - For an iterator method like
Cross(): When you call it (e.g.,_cross = Cross();), something totally different happens:- The runtime does not execute any code inside the
Cross()method body right away. - Instead, it creates and returns a state machine object that implements the
IEnumeratorinterface. This object keeps track of where we left off in the iterator method's execution. - The method body only starts running when you call
MoveNext()on this enumerator object. It will run until it hits ayield return(pauses execution and returns the current value) oryield break(stops execution entirely).
- The runtime does not execute any code inside the
Wait, Why Did You See a Null Enumerator?
If you're seeing _cross as null after calling Cross(), that's likely one of two scenarios:
- Your
Cross()method doesn't contain anyyield returnoryield breakstatements. Even if it's declared to returnIEnumerator, without yield keywords, the compiler treats it like a regular method—and if there's no explicitreturnstatement, it will returnnullby default. In this case, the method body still won't execute unless you explicitly run it (but since it's an iterator without yield, this is a code smell and should trigger a compiler warning). - You might be misreading the debugger output: Iterator state machines are often displayed with internal fields that look null, but the enumerator itself is a valid object. Try checking the actual type of
_cross—it should be something likeGameMoves+<Cross>d__X(where X is a number), which is the compiler-generated state machine type.
Example to Illustrate
Let's make this concrete with a simplified version of your Cross() method:
public IEnumerator Cross() { Console.WriteLine("Cross() method starting"); yield return "First cross move"; Console.WriteLine("After first yield"); yield return "Second cross move"; }
- When you run
_cross = Cross();: No console output,_crossholds a state machine instance. - When you call
_cross.MoveNext(): The console prints "Cross() method starting", the method runs until the firstyield return, and_cross.Currentbecomes "First cross move". - Call
_cross.MoveNext()again: Console prints "After first yield", runs to the secondyield return,_cross.Currentis "Second cross move". - Call
_cross.MoveNext()a third time: Returnsfalse, indicating the iterator is done.
To Sum Up
- Iterator methods delay execution until you trigger it via
MoveNext()on the returned enumerator. - The initial call to
Cross()only creates the state machine—it doesn't run any of the method's logic. - A null enumerator usually means missing yield statements in your iterator method, so double-check that code!
内容的提问来源于stack exchange,提问作者Nadav F
相关产品推荐
相关产品推荐

