-2

I have found an interesting thing. c#,.NET 4.0. I have a class what represents the IDisposable interface. In the mentioned class I have a function, what returns with IEnumerable with yield return. At call, the controll jumps over that function. Do not step in. Example:

class Program
{
    static void Main(string[] args)
    {
        using (DispClass d = new DispClass())
        {
            d.Get2();
            d.Get1();
        }
    }

}

public class DispClass: IDisposable
{
    public DispClass()
    {
        Console.WriteLine("Constructor");
    }
    public void Dispose()
    {
        Console.WriteLine("Dispose");
    }
    public int Get1()
    {
        Console.WriteLine("Getting one");
        return 1;
    }
    public IEnumerable<int> Get2()
    {
        Console.WriteLine("Getting 1");
        yield return 1;
        Console.WriteLine("Getting 2");
        yield return 2;
    }

}

The output: "Constructor" "Getting one" "Dispose"

Where are the "Getting 1", "Getting 2"? Without yield return with returning a local list I can see these...

Please explain!

Tamas
  • 35
  • 3
  • 2
    You need to consume the `IEnumerable` returned from the call to `Get2`, perhaps with a `foreach` statement? – spender Oct 05 '16 at 16:09
  • 2
    `yield return` causes the method to (magically) return an enumerator object which contains the code in your method. It just sits there waiting to be enumerated, but you never enumerate it. How do you think that makes it feel? Try `d.Get2().ToList();` – 15ee8f99-57ff-4f92-890c-b56153 Oct 05 '16 at 16:10
  • 2
    P.S. this is the whole purpose of `yield return`: Somebody calls your method, but none of the code actually executes until it's actually required to. This allows a caller to, for example, iterate through only *part* of a lengthy foreach loop in your method, thus saving time and resources. It's a feature, not a bug. – 15ee8f99-57ff-4f92-890c-b56153 Oct 05 '16 at 16:12
  • You may want to read http://stackoverflow.com/questions/39476/what-is-the-yield-keyword-used-for-in-c (and similar posts about `yield return`) – Alexei Levenkov Oct 05 '16 at 16:19
  • Also please read [MCVE] guidance on posting samples - if you carefully follow it your post would not talk about completely unrelated `IDisposable` implementation... Consider [edit] your post to remove unrelated IDisposable references and most of the code or clarify why you believe it is important part of the post. – Alexei Levenkov Oct 05 '16 at 16:21

2 Answers2

5

This is expected behavior and by design. When you use yield, what's actually happening is that the Get2 method is returning an instance of a type that is automatically implemented by the compiler. That types implements IEnumerable<T> interface. The code inside your iterator method doesn't actually get called until the enumerable object is enumerated. Since you aren't enumerating over the result of the Get2 call, your code is never being called. To force it, use something like ToArray() or ToList():

 d.Get2().ToList();
Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
0

the code inside the method Get2() will execute only when you iterate over the IEnumerable returned by the method. Since the IEnumerable in this case contains two elements, it will enter this code twice - during the first iteration it will execute the 1st two lines and exit the function at "yield return 1; During the next iteration it will enter the function and start execution at the line "Console.WriteLine("Getting 2");" and continue form there onwards.

Consequently if you do not iterate over both the items i.e. after getting the value 1, you do not move to the next item in the IEnumerable, then the function will not be entered again. Try changing your program to the following code to get a better understanding.

    static void Main(string[] args)
    {
        using (DispClass d = new DispClass())
        {
            var lst = d.Get2();
            //d.Get1();

            foreach (var a in lst)
            {
                break;
            }
        }
        Console.ReadKey();
    }
Parag Patil
  • 156
  • 7