简体   繁体   中英

Returning IEnumerable<T> with yield from IDisposable instance

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!

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();

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 ie 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();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM