for each loop in an iterator method

Check out this program:

static class Program
{
  static void Main()
  {
    GetLinks();
    Console.WriteLine("Program failed!");
  }

  static IEnumerable<string> GetLinks()
  {
    throw new Exception();
    foreach (var item in new string[] { })
      yield return item;
  }
}

It's very weird but the result of this program is Program failed!, meaning the GetLinks function is not even called. What's the explanation of this behavior?

Check it out for yourself.

Answers


Iterator blocks are lazy. You need to call it by invoking it in a foreach or something. Code inside your iterator block will execute only on the first call to MoveNext which foreach will do for you.

As of now you're just preparing the query, you need to materialize it with the call to GetEnumerator followed by MoveNext.

For example following code will fail as expected.

static void Main()
{
    foreach(var item in GetLinks())
        Console.WriteLine(item );
    Console.WriteLine("Program failed!");
}

Further reading Iterator block implementation details


An iterator block is a somewhat special method... When it sees the yield return keyword, the compiler generates a class that implements IEnumerator<T> (and also IEnumerable<T>, depending on the return type of your method), and changes your method to return an instance of this class. The original body of your method is transformed into the MoveNext method of the enumerator. This means that the body of your method is only executed when the result is enumerated. Just calling the method has no effect if you don't enumerate the result. In other words, iterator blocks are executed lazily.

That's why methods implemented as iterator blocks must validate their arguments in a separate method:

public IEnumerable<string> Foo(string arg)
{
    if (arg == null) throw new ArgumentNullException();
    return FooIterator(arg);
}

private IEnumerable<string> FooIterator(string arg)
{
    yield return arg;
}

Need Your Help

How to deserialize date (milliseconds) with JSON.NET?

c# .net json.net

I'm working with a response like the following:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.