一个可以在C#中的表达式树中使用的类型是否意味着可以在Lambda表达式中使用?他们有亲戚关系吗



我正在阅读这份文件,其中一条注释是,

您可能希望始终使用ValueTuple而不是Tuple和匿名类型,但您应该考虑一些折衷方案。ValueTuple类型是可变的,而Tuple是只读的匿名类型可以在表达式树中使用,而元组不能下表概述了一些关键差异。[强调矿]

这不是关于元组或匿名类型本身的问题,而是关于概念的问题。

表达式树在.NET中表示为指向其他对象的对象,这些对象又指向其他对象。例如,考虑以下表达式树:

Expression expr = () => DateTime.Now.Hour > 18;

实际上,我们不能在System.Linq.Expressions中的大多数类型上编写new <X>。但是,如果我们可以把表达式树写成一系列对象创建和初始化,它可能看起来像这样:

new Expression<Func<bool>> {
NodeType = ExpressionType.Lambda,
Type = typeof(Func<bool>),
Body = new BinaryExpression {
NodeType = ExpressionType.GreaterThan,
Type = typeof(bool),
Left = new MemberExpression {
Type = typeof(int),
Expression = new MemberExpression {
Type = typeof(DateTime),
Member = typeof(DateTime).GetProperty("Now")
},
Member = typeof(DateTime).GetProperty("Hour")
},
Right = new ConstantExpression {
Type = typeof(int),
Value = 18
}
},
ReturnType = typeof(bool)
}

有两种创建表达式树的基本方法:

  1. 让编译器执行此操作。将lambda表达式语法设置为Expression<TDelegate>类型的变量、属性或参数。C#编译器会自动将您编写的代码转换为一个完整的表达式树(如上所述(。

  2. 调用System.Linq.Expressions.Expression上的工厂方法类似这样的东西:

    // using static System.Linq.Expressions.Expression
    Lambda(
    GreaterThan(
    MakeMemberAccess(
    MakeMemberAccess(null,
    typeof(DateTime).GetProperty("Now")
    ),
    typeof(DateTime).GetProperty("Hour")
    ),
    Constant(18)
    )
    )
    

因为C#编译器中创建表达式树的部分已经很长时间没有更新了,所以它无法处理许多较新的C#构造(如值元组(。

但是,您总是可以使用工厂方法,并使用您可能想要的任何.NET类型来构造表达式树。


(注意。我写了一个库,可以生成表达式树的字符串表示,比如这个答案中的那些。(

最新更新