I just had a case with a method using yield return not throwing an ArgumentException which I expected. I have reconstructed the case with the simpliest possible classes here:
class Program
{
static void Main(string[] args)
{
try
{
var listA = FooA(count: 0);
Console.WriteLine("A did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("A threw exception!");
}
try
{
var listB = FooB(count: 0);
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
Console.ReadLine();
}
private static IEnumerable<int> FooA(int count)
{
if(count == 0)
throw new ArgumentException("Count must be above 0");
var list = new List<int>();
for (var i = 0; i < count; i++)
{
list.Add(i);
}
return list;
}
private static IEnumerable<int> FooB(int count)
{
if (count == 0)
throw new ArgumentException("Count must be above 0");
for (var i = 0; i < count; i++)
{
yield return i;
}
}
}
Output:
A threw exception!
B did not throw exception!
Can some one please explain to me why FooB does not throw an exception while FooA does?
It's because FooB
is never even evaluated.
When you call a method, that method is called immediately. When you use yield
and return an enumerable, that method is only called when something needs to use the value returned, and only a single item at a time; this is the benefit of yield
ing.
So, if you add something that uses the value
try
{
var listB = FooB(count: 0);
Console.WriteLine(listB.First()); // use the IEnumerable returned
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
You will see your expected result.
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