Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a breakpoint in a lambda expression?

I would like to debug a lambda that is called in an expression tree. Unfortunately, the breakpoint is never hit.

Here's a full Console Program to play with:

private static void Main()
{
    var evalAndWrite = EvalAndWrite(x => x + 1 /* a breakpoint here is never hit */);
    evalAndWrite(1);
    Console.ReadLine();
}

private static Action<int> EvalAndWrite(Expression<Func<int, int>> expr)
{
    var result = Expression.Variable(typeof(int), "result");
    var assign = Expression.Assign(result, expr.Body);
    var writeLine = Expression.Call(typeof(Console), nameof(Console.WriteLine), null, result);
    var body = Expression.Block(new[] {result}, assign, writeLine);
    return Expression.Lambda<Action<int>>(body, expr.Parameters[0]).Compile();
}

If I set a breakpoint within the lambda (i.e. at x + 1 using F9) the whole line gets breaked at but not the lambda when it is actually being executed.

Looking at the debug view of the body I see:

.Block(System.Int32 $result) {
    $result = $x + 1;
    .Call System.Console.WriteLine($result)
}

which indicates a copy-semantic: the logic of the lambda has been "inlined" and I suppose the connection to the original lambda is lost. Or would there be any trick to making debugging of the original lambda within Visual Studio possible?

like image 756
Dejan Avatar asked Mar 15 '17 01:03

Dejan


People also ask

How do you create a breakpoint on a lambda function?

You can use Ctrl+F8 to add a breakpoint. Then the lambda expression that the cursor is placed on will be selected in the list.

How do you set breakpoints?

Set breakpoints in source code To set a breakpoint in source code: Click in the far left margin next to a line of code. You can also select the line and press F9, select Debug > Toggle Breakpoint, or right-click and select Breakpoint > Insert breakpoint. The breakpoint appears as a red dot in the left margin.

How do you debug a lambda expression?

We can use different IDE's like Netbeans, IntelliJ, and Eclipse to debug the lambda expressions in Java. It is always possible to create multi-line lambda expressions and use print statements to display the values of a variable. The debugger can also provide additional information about the state of a java program.

How do you put a breakpoint in all methods?

Press F3 and then press F9 to add a breakpoint.


1 Answers

An Expression is data, not code. It can be turned into code, by calling Compile(), but until you do that, it's not code. It's data. And the debugger can only set breakpoints in code.

More specifically, the debugger uses the information in the .pdb file generated at compile time, to correlate the compiled code with the original source code. When you use a lambda to define an Expression, you're not generating any compiled code at that time, so there's nothing in the .pdb that would point the debugger to the code in your lambda. You're generating an expression tree, which is a kind of data that can be turned into code later at run-time.

(Not that it is in theory impossible for the debugger to support this, but it would take a lot of extra work, work that hasn't been done, as far as I know.)

Depending on what your ultimate goal is, you might be able to achieve what you want by adding a level of indirection. For example:

private static void Main()
{
    Func<int, int> e = x => x + 1; // set breakpoint here

    var evalAndWrite = EvalAndWrite(x => e(x));
    evalAndWrite(1);
    Console.ReadLine();
}

This approach, of course, will hide the actual expression body from the EvalAndWrite() method. If you were using expressions as a way of "decompiling" the original lambda so you could inspect it or otherwise use the individual parts of the body for some reason, then the above wouldn't be useful. But in your example, you don't seem to be doing that. So maybe this will be enough for your needs.

like image 186
Peter Duniho Avatar answered Oct 18 '22 20:10

Peter Duniho