VB.NET:"语句lambdas无法转换为表达式树"编译时错误

Rém*_*ery 8 .net vb.net lambda

为什么我可以执行以下操作:

Dim qNodes As IQueryable(Of XmlNode) = xDoc.ChildNodes.AsQueryable()
Dim test = qNodes.Where(Function(node) True)
Run Code Online (Sandbox Code Playgroud)

虽然以下给出了我在标题中说明的错误:

Dim qNodes As IQueryable(Of XmlNode) = xDoc.ChildNodes.AsQueryable()
Dim test = qNodes.Where(Function(node)
                               Return True
                           End Function)
Run Code Online (Sandbox Code Playgroud)

我真的不明白.

SLa*_*aks 11

VB.Net支持两种lambda表达式:

  • 表达式lambda包含单个表达式并隐式返回表达式.
    例如:Function(x) x.ToString()

  • 语句lambdas包含一个或多个语句,必须显式使用Return关键字(如果它们返回值)
    这些是VB.Net 2010的新增内容.
    例如:

    Sub(x)
        Logger.Log(x)
        Console.WriteLine(x)
    End Sub
    
    Run Code Online (Sandbox Code Playgroud)

Where方法和所有其他IQueryable方法采用表达式树.
编译器可以自动将表达式 lambdas而不是语句lambdas 编译到表达式树中.

您的第二个示例尝试将语句 lambda作为一个Expression(Of Func(Of T, Boolean)),但编译器无法执行此操作.


Han*_*ant 7

这在VB.NET 10语言规范的第11.1节中说明:

lambda方法和表达式树之间的确切转换可能无法在编译器的版本之间修复,超出了本规范的范围.对于Microsoft Visual Basic 10.0,所有lambda表达式都可以转换为表达式树,但受以下限制:

  1. 只有没有ByRef参数的单行lambda表达式才能转换为表达式树.在单行Sub lambdas中,只有调用语句可以转换为表达式树.
  2. 如果使用较早的字段初始值设定项初始化后续字段初始值设定项,则无法将匿名类型表达式转换为表达式树,例如New With {.a = 1,.b = .a}
  3. 如果正在初始化的当前对象的成员在其中一个字段初始值设定项中使用,则无法将对象初始值设定项表达式转换为表达式树,例如,使用{.a = 1,.b = .Method1()}的新C1
  4. 多维数组创建表达式只有在显式声明其元素类型时才能转换为表达式树.
  5. 后期绑定表达式无法转换为表达式树.
  6. 当变量或字段通过ByRef传递给调用表达式但没有与ByRef参数完全相同的类型时,或者当属性传递给ByRef时,正常的VB语义是参数的副本传递ByRef及其最终值然后复制回变量或字段或属性.在表达式树中,不会发生复制.

所有这些限制也适用于嵌套的lambda表达式.

这是您遇到的第一个项目中的限制.引言留下了足够的空间来假设这将在未来的版本中得到解决,当然还有很多工作要做.Connect.microsoft.com是一个鼓励他们的好地方.我无法检查是否已经为此打开了一个反馈项目,该网站现在正处于fritz状态.