I'm unable to understand why Program.Fetch1
and Program.Fetch2
do not result in the exact same execution order. The only difference is that Program.Fetch1
is calling Program.Fetch
to do the actual fetch operation.
class Program
{
static IEnumerable<int> Fetch1()
{
using (Context c = new Context())
{
return Fetch(c);
}
}
static IEnumerable<int> Fetch(Context c)
{
foreach (int i in c.Fetch())
{
yield return i;
}
}
static IEnumerable<int> Fetch2()
{
using (Context c = new Context())
{
foreach (int i in c.Fetch())
{
yield return i;
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Fetch1:");
foreach (int i in Fetch1())
{
Console.WriteLine(i);
}
Console.WriteLine("Fetch2:");
foreach (int i in Fetch2())
{
Console.WriteLine(i);
}
}
}
class Context : IDisposable
{
public void Dispose()
{
Console.WriteLine("Context.Dispose");
}
public IEnumerable<int> Fetch()
{
return new int[] { 1, 2 };
}
}
Output:
Fetch1:
Context.Dispose
1
2
Fetch2:
1
2
Context.Dispose
My only guess is that Context.Dispose
is called first in Program.Fetch1
because the scope of the using declaration was already left. But this is true for Program.Fetch1
as well. So why do those method behave differently?
Update: My question is a duplicate of yield return statement inside a using() { } block Disposes before executing
The yield return statement returns one element at a time. The return type of yield keyword is either IEnumerable or IEnumerator . The yield break statement is used to end the iteration. We can consume the iterator method that contains a yield return statement either by using foreach loop or LINQ query.
An object which will return data, one element at a time. Technically speaking, a Python iterator object must implement two special methods, __iter__() and __next__() , collectively called the iterator protocol. An object is called iterable if we can get an iterator from it.
The yield keyword, first introduced in C# 2.0, T returns an object that implements the IEnumerable interface. The IEnumerable interface exposes an IEnumerator that can used to iterate a non-generic collection using a foreach loop in C#.
Code is written after the yield statement in the next function call is executed. Code introduced after the return statement will not be executed; instead, it will be ignored. It has the ability to run many times.
That's because those options are actually different:
Fetch
and Fetch2
, using yield
, create a state machine to be able to return an unmaterialized IEnumerable
.Fetch1
you are simply calling Fetch
and returning the generated state machine and disposing of the context without waiting for that IEnumerable
to actually be materialized.Basically, the difference is that in Fetch2
you have a layer of deferred execution (using yield
) while in Fetch1
you don't, which means the using scope ends immediately when you return.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With