2009-09-24 8 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" semble être un IEnumerable avec v1 et v2 (params) comme champs et "Test1" n'est pas appelé.rupture de rendement; - comportement fou

"Test2" fonctionne un "conçu" :)

ce qui se passe?

Répondre

15

Test1est appelé, mais à moins que vous itérer le résultat, vous ne serez pas touché un point d'arrêt sur yield break.

Fondamentalement Test1 est transformé en une machine d'état qui implémente IEnumerable pour vous ... mais tout le corps de votre méthode est à l'intérieur de cette machine d'état, et à moins que vous utilisez la machine d'état en appelant GetEnumerator() puis MoveNext() (ou en utilisant une boucle foreach) vous ne verrez pas votre corps s'exécuter.

Voir mon general iterator article et mon iterator implementation article pour plus d'informations, ainsi que deux des messages de blog d'Eric Lippert: Psychic Debugging part one et Psychic Debugging part two.

1

Depuis que vous avez mentionné Python, je vais souligner que les générateurs en Python fonctionnent de manière similaire aux générateurs en C#. Il y a juste la petite différence que yield break seul peut transformer une méthode C# en générateur, alors que l'équivalent Python de raise StopIteration ne le fera pas.

>>> 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