The following code snippet is meant to catch any exceptions while enumerating and ignore that particular item.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
DataProvider[] dataproviders = new DataProvider[]
{
new DataProvider(itemCount: 3, throwAfter: 1),
new DataProvider(itemCount: 4),
};
var output = ListEnumerable(dataproviders).ToList();
// We'll never get there. I excepted items from second dataprovider here
Console.WriteLine("Success");
}
private static IEnumerable<Item> ListEnumerable(IEnumerable<DataProvider> providers)
{
ArgumentException providerException = null;
foreach (DataProvider provider in providers)
{
providerException = null;
try
{
return provider.GetData();
}
catch (ArgumentException ex)
{
// Expected to catch the argumentexception thrown in GetData here. This never happens
providerException = ex;
Console.WriteLine("Exception caught");
}
}
if (providerException != null)
{
throw providerException;
}
return Enumerable.Empty<Item>();
}
private class DataProvider
{
public DataProvider(int itemCount = 3, int throwAfter = -1)
{
this.ItemCount = itemCount;
this.ThrowAfter = throwAfter;
}
public int ItemCount { get; }
public int ThrowAfter { get; }
public IEnumerable<Item> GetData()
{
for (int i = 0; i < this.ItemCount; ++i)
{
if (i == this.ThrowAfter)
{
throw new ArgumentException("Thrown after " + i);
}
yield return new Item();
}
}
}
private class Item
{
public string Name = Guid.NewGuid().ToString();
}
}
I expected the exception to be thrown in ListEnumerable
and then go to the next item. But, running the snippet causes the exception to be thrown in main.
Why is this happening? What is the correct way to express this with lazy evaluation of the data still intact?