0

Is there a way to insert debug info into .NET expression tree, so that it's shown in the exception trace (e.g., source code location and custom function name).

For example, given the code (that defines a function that divides its two arguments, and calls it with second parameter being 0):

// Define the lambda expression
var x = Expression.Parameter(typeof(int), "x");
var y = Expression.Parameter(typeof(int), "y");
var op = Expression.Divide(x, y);
var debug = Expression.DebugInfo(
    Expression.SymbolDocument("test.txt"),
    1, 5, 4, 13);
var bl = Expression.Block(debug, op);
var lambdaExpr = Expression.Lambda<Func<int, int, int>>(
    bl,
    new[] { x, y });

// Compile the lambda expression to a delegate
var compiled = lambdaExpr.Compile();

// Create a function that invokes the compiled delegate with some arguments
Func<int, int, int> invokeDelegate = (xArg, yArg) => compiled(xArg, yArg);

// Invoke the function with some arguments
invokeDelegate(20, 0);

The resulting stack trace ends up being:

Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
   at lambda_method1(Closure , Int32 , Int32 )
   at ExpressionTreeExample.<>c__DisplayClass0_0.<Main>b__0(Int32 xArg, Int32 yArg) in .../workspace/test/Program.cs:line 23
   at ExpressionTreeExample.Main() in .../workspace/test/Program.cs:line 26

In this example, is there a way to add debug information to the expression so that "test.txt" (and other provided information) is shown in the exception trace?

Note: I'm interested in .NET Core, not Framework. Thanks!

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Pero P
  • 31
  • 1
  • It seems that this is not possible since `DebugInfoGenerator.CreatePdbGenerator()` API is obsoleted ATM. – Guru Stron Apr 28 '23 at 00:25
  • I wonder what is the purpose of `Expression.DebugInfo` then? – Pero P Apr 28 '23 at 07:53
  • Legacy. Maybe the API will be enabled back later. – Guru Stron Apr 28 '23 at 09:04
  • If you just want the exception to have more information, why not wrap the body of your expression in a try-catch (using `Expression.TryCatch`) and throw a new exception containing enough metadata for you to be able to debug, with the original exception as the inner exception? – Simon MᶜKenzie Apr 28 '23 at 10:33
  • I guess it would be a bit expensive to add try-catch at each place where exception would happen. – Pero P Apr 28 '23 at 20:09
  • When you say "expensive", are you talking about performance, or development effort? Adding a single top-level try-catch to your expression wouldn't be very expensive in terms of dev time, and for performance, the try-catch [shouldn't be a problem unless it throws a lot](https://stackoverflow.com/a/3480151/622391). – Simon MᶜKenzie Apr 29 '23 at 21:07

0 Answers0