2009-09-24 5 views
6
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Collections; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main (string[] args) 
     { 
      var test1 = Test1(1, 2); 
      var test2 = Test2(3, 4); 
     } 

     static IEnumerable Test1(int v1, int v2) 
     { 
      yield break; 
     } 

     static IEnumerable Test2 (int v1, int v2) 
     { 
      return new String[] { }; 
     } 
    } 
} 

«test1» похоже IEnumerable с v1 и v2 (params) в качестве полей, а «Test1» НЕ вызывается.разрыв выхода; - сумасшедшее поведение

"Test2" работает "разработан" :)

Что происходит?

ответ

15

Test1является называется, но если вы не перебирать результат, вы не достиг точки останова на yield break.

В основном Test1 превращается в государственную машину, которая реализует IEnumerable для вас ... но все тело вашего метода заключается в том государственной машины, и если вы не использовать состояние машины, вызвав GetEnumerator(), а затем MoveNext() (или используя цикл foreach), вы не увидите, что ваше тело выполнено.

Смотрите мой general iterator article и мою iterator implementation статью для получения дополнительной информации, а также два из блога Эрика Липперта: Psychic Debugging part one и Psychic Debugging part two.

1

Поскольку вы упомянули Python, я хочу указать, что генераторы в Python работают аналогично генераторам на C#. Есть только небольшая разница, что только yield break может преобразовать метод C# в генератор, тогда как эквивалент Python raise StopIteration не будет.

>>> def f(): 
...  print "Beginning of generator" 
...  if False: yield 
...  print "End of generator" 
... 
>>> it = f() 
>>> it 
<generator object at 0x94fae2c> 
>>> it.next() 
Beginning of generator 
End of generator 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration