Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debugging LINQ on a per-element basis

I love LINQ statements for the expressive syntax and other convenient features. However, I find it very troublesome to debug them sometimes. Specifically, when I run a LINQ statement on a collection and one of the elements in the collection causes an exception, how can I figure out what the problem input was and where the problem came from?

Imagine I have a text file with 1000 real numbers:

0.46578
12.314213
1.444876
...

I am reading this as a List<string> and loading it into a more specific data structure:

var file_contents = File.ReadAllLines("myfile.txt");
var data = file_contents.Select(s => double.Parse(s));

Now, for this particular input, I didn't bother to look at it carefully and it turns out the 876th line contains (line numbers shown):

875    5.56786450
876    Error: Could not calculate value.
878    0.0316213

For whatever reason (perhaps the file was generated by a script that malfunctioned). My LINQ method chain will of course throw an exception. The problem is, how do I figure which element of the list caused the exception, and what its value was?

To clarify, if instead I used a for-loop:

var data = new List<double>();
foreach(var row in file_contents)
{
    var d = double.Parse(row);
    data.Add(d);
}

Then the exception would highlight the string which calls double.Parse, and I would be able to mouse over row to easily see what the problem input was.

I can, of course, use Resharper to convert my LINQ statements into for-loops, and then debug them, but is there a better way?

like image 456
Superbest Avatar asked May 01 '13 13:05

Superbest


3 Answers

Put a conditional breakpoint on the lambda function, where the condition is s.StartsWith("5.56"). You just need to have your cursor on the lambda and press F9. Assuming you're using visual studio.

like image 98
Dax Fohl Avatar answered Nov 06 '22 04:11

Dax Fohl


var data = file_contents.Select(s => {
    try
    {
       return double.Parse(s);

    }
    catch
    {
       throw; //breakpoint?
    }
});
like image 36
spender Avatar answered Nov 06 '22 05:11

spender


Disclaimer: I work for OzCode

LINQ debugging is hard borderline impossible using Visual Studio. I suggest you try using OzCode.

This is what your code looks when debugging (the exception in on the 6th item). Debugging LINQ exception

You can tell which item caused the exception by investigating the items that where passed to the Select clause - and since the last one triggered the exception - it's easy to find the offending value.

If you're interested you can try OzCode's LINQ debugging - we've just started an EAP

like image 23
Dror Helper Avatar answered Nov 06 '22 05:11

Dror Helper