33

What is the difference between yield keyword in Python and yield keyword in C#?

maxyfc
  • 11,167
  • 7
  • 37
  • 46

3 Answers3

34

C#'s yield return is equivalent to Python's yield , and yield break is just return in Python.

Other than those minor differences, they have basically the same purpose.

John Millikin
  • 197,344
  • 39
  • 212
  • 226
  • 1
    yield break in C# is not exactly equivalent to Python's return. If your function does nothing except yield break( return in Python), you will get a empty Enumerator while a None in python. – Sonic Lee Jun 18 '11 at 09:01
  • 2
    That's a minor syntactic quirk of Python; you can use `return; yield` to get an empty generator. – John Millikin Aug 06 '11 at 22:16
  • 1
    Also `yield` in Python is an expression that can receive values from the iterating site. `yield return` is a statement. – Elazar Aug 29 '17 at 20:48
  • 1
    But NO yield from in C# which is very sad. To emulate similar behaviour, there's a lot of boilerplate code which can't be put into a function. **EDIT:** If you're using Unity, it does have nested coroutines! – jeromej Jul 25 '18 at 14:29
15

The most important difference is that python yield gives you an iterator, once it is fully iterated that's over.

But C# yield return gives you an iterator "factory", which you can pass it around and uses it in multiple places of your code without concerning whether it has been "looped" once before.

Take this example in python:

In [235]: def func1():
   .....:     for i in xrange(3):
   .....:         yield i
   .....:

In [236]: x1 = func1()

In [237]: for k in x1:
   .....:     print k
   .....:
0
1
2

In [238]: for k in x1:
   .....:     print k
   .....:

In [239]:

And in C#:

class Program
{
    static IEnumerable<int> Func1()
    {
        for (int i = 0; i < 3; i++)
            yield return i;
    }

    static void Main(string[] args)
    {
        var x1 = Func1();
        foreach (int k in x1) 
            Console.WriteLine(k);

        foreach (int k in x1)
            Console.WriteLine(k);
    }
}

That gives you:

0
1
2
0
1
2
Paul
  • 151
  • 1
  • 3
1

An important distinction to note, in addition to other answers, is that yield in C# can't be used as an expression, only as a statement.

An example of yield expression usage in Python (example pasted from here):

def echo(value=None):
  print "Execution starts when 'next()' is called for the first time."
  try:
    while True:
       try:
         value = (yield value)
       except GeneratorExit:
         # never catch GeneratorExit
         raise
       except Exception, e:
         value = e
     finally:
       print "Don't forget to clean up when 'close()' is called."

generator = echo(1)
print generator.next()
# Execution starts when 'next()' is called for the first time.
# prints 1

print generator.next()
# prints None

print generator.send(2)
# prints 2

generator.throw(TypeError, "spam")
# throws TypeError('spam',)

generator.close()
# prints "Don't forget to clean up when 'close()' is called."
Max Desiatov
  • 5,087
  • 3
  • 48
  • 56
  • But from your link expression usage is only beneficial for generators, which would appear to be achievable in C# via a call to `GetEnumerator` on the resulting `IEnumerable` you would return from yielding method. – Kenneth K. Aug 21 '18 at 13:19
  • @KennethK. I'm not disproving that in my answer in any way. The question asked about differences in `yield` keyword, not the differences in how returned generator/iterator objects may be treated – Max Desiatov Aug 21 '18 at 14:39
  • I don't disagree, but your argument is "there is no yield expression in C#" to which one might resolve, "then I can't do the same thing in C# that I can do in Python", but that doesn't seem to be the case. The fact that C# can't do expression-yields doesn't mean you can't achieve the same functionality (unless I misunderstand the Python functionality, which is certainly possible since Python isn't my forte). – Kenneth K. Aug 21 '18 at 14:44
  • 1
    As far as I understand, even when you're able to call `GetEnumerator` on the result, you won't be able to pass values into the generator function, which is what `yield` expression evaluates in Python version. There is no method on `IEnumerator` interface that matches the semantics of Python's `send()` generator method. – Max Desiatov Aug 21 '18 at 14:58
  • OK, I understand what you're saying now. – Kenneth K. Aug 21 '18 at 15:20