Does Expression.ToString() work?

佐手、 提交于 2020-05-27 21:25:53

问题


I have a generated lambda, but when I want to watch it's like a normal lambda it just doesn't show anything. When I call expr.Body.ToString() I get following:

{var compareA; ... }

But DebugView for expression works fine:

.Lambda #Lambda1<System.Comparison`1[XLinq.Test.Comparers.CustomComparerTest+Test]>(
    XLinq.Test.Comparers.CustomComparerTest+Test $x,
    XLinq.Test.Comparers.CustomComparerTest+Test $y) {
    .Block(System.Int32 $compareA) {
        $compareA = .Call ($x.A).CompareTo($y.A);
        .If ($compareA != 0) {
            .Return #Label1 { $compareA }
        } .Else {
            .Block(System.Int32 $compareB) {
                $compareB = .Call ($x.B).CompareTo($y.B);
                .If ($compareB != 0) {
                    .Return #Label1 { $compareB }
                } .Else {
                    .Block(System.Int32 $compareC) {
                        $compareC = .Call ($x.C).CompareTo($y.C);
                        .If ($compareC != 0) {
                            .Return #Label1 { $compareC }
                        } .Else {
                            .Block(System.Int32 $compareD) {
                                $compareD = .Call ($x.D).CompareTo($y.D);
                                .If ($compareD != 0) {
                                    .Return #Label1 { $compareD }
                                } .Else {
                                    .Default(System.Void)
                                }
                            }
                        }
                    }
                }
            }
        };
        .Label
            0
        .LabelTarget #Label1:
    }
}

Why am I getting this result?


回答1:


This is because the Expression.ToString override relies on the internal ExpressionStringBuilder visitor type, which produces a greatly simplified expression tree representation.

The debug view provided by custom debugger proxies defined on each Expression-derived type (i.e. [DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))] on BlockExpression) provides a lot more information, as you've found out, by exposing the output of a more verbose DebugViewWriter visitor (also internal).

Unfortunately, you can't get that output easily outside of debug scenarios, unless you're willing to use reflection to fetch the value of a private DebugView property (defined in System.Linq.Expressions.Expression) as follows:

Expression<Func<string, int>> expr = str => str.Length;
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
PropertyInfo debugViewProp = typeof(Expression).GetProperty("DebugView", flags);
MethodInfo debugViewGetter = debugViewProp.GetGetMethod(nonPublic: true);
string debugView = (string)debugViewGetter.Invoke(expr, null);

Produces

.Lambda #Lambda1<System.Func`2[System.String,System.Int32]>(System.String $str) {
    $str.Length
}

As always, Reference Source is your best friend:

http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Ast/Expression.cs,aa5f054356a8a17d



来源:https://stackoverflow.com/questions/34116591/does-expression-tostring-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!