c# - Expression.ToString() 有效吗?

标签 c# .net lambda linq-expressions

我有一个生成的 lambda,但是当我想看它就像一个普通的 lambda 时,它只是不显示任何内容。当我调用 expr.Body.ToString() 时,我得到以下信息:

{var compareA; ... }

但是表达式的 DebugView 工作正常:

.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:
    }
}

为什么我会得到这个结果?

最佳答案

这是因为 Expression.ToString 重写依赖于内部 ExpressionStringBuilder 访问者类型,它会生成一个大大简化的表达式树表示。

由在每个 Expression 派生类型上定义的自定义调试器代理提供的调试 View (即 [DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))] on BlockExpression ) 通过公开更详细的 DebugViewWriter 访问者(也是内部的)的输出,提供了更多信息,正如您所发现的。

不幸的是,您无法在调试场景之外轻松获得该输出,除非您愿意使用反射来获取私有(private) DebugView 属性(在 System. Linq.Expressions.Expression) 如下:

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);

生产

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

一如既往,Reference Source 是您最好的 friend :

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

关于c# - Expression.ToString() 有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34116591/

相关文章:

c# - 如何使用/理解 lambda 表达式?

c# - 如何在运行时才知道类型时创建 Expression.Lambda?

c# - 替换为通配符

.net - Windows 窗体应用程序中的面板与 GroupBox

c# - .net core 路由,用通用路由了解什么应用程序调用

c# - 工具提示中的超链接

c# - 为什么向结构体添加一个额外的字段会大大提高其性能?

node.js - Nodejs lambda 请求函数获取 411 Length required

c# - ReceiveAsync 与 BeginReceive 的性能

c# - 模拟在 ASP.NET MVC 中工作吗