Smuggling exceptions out of try-catches with IEnumerable
The code in this post is from a talk by Erik Meijer, I claim no credit.
Take a look at this screenshot:
Pretty wacky huh? Visual Studio has broken into debug mode even though the division is clearly wrapped in a try-catch. Take a guess at what’s going on before reading on.
Here’s the full code listing:
static void Main(string[] args) { var xs = new[] { 1, 2, 3, 0 }; IEnumerable q = null; try { q = from x in xs select 1 / x; } catch { } foreach (var z in q) { Console.WriteLine(z); } }
The obvious expectation is that division-by-zero will be caught by the try-catch. Alas, the division does not happen in the scope of the try statement. Instead, due to the deferred execution paradigm of IEnumerable, it happens on a by-need basis in the for-loop. From there the exception can propogate unopposed to the top af the stack. Haskell, where lazy evaluation dominates, avoids exceptions (and other messy side effects) alltogether, partly for reasons demonstrated by this example.
UPDATE: As Wayne points out, fixing this is as easy as extending the try
to cover the enumeration. The point of this post was mainly to poke fun at the Visual Studio debugger and to point out that lazy evaluation can bite you if you’re not careful.
Leave a Reply