Why can I do the following :
Dim qNodes As IQueryable(Of XmlNode) = xDoc.ChildNodes.AsQueryable()
Dim test = qNodes.Where(Function(node) True)
although the following gives the error I stated in the title :
Dim qNodes As IQueryable(Of XmlNode) = xDoc.ChildNodes.AsQueryable()
Dim test = qNodes.Where(Function(node)
Return True
End Function)
?
I really don't get it.
VB.Net supports two kinds of lambda expressions:
Expression lambdas contain a single expression and implicitly return the expression.
For example: Function(x) x.ToString()
Statement lambdas contain one or more statements and must explicitly use the Return
keyword (if they return a value)
These are new to VB.Net 2010.
For example:
Sub(x)
Logger.Log(x)
Console.WriteLine(x)
End Sub
The Where
method, and all other IQueryable
methods, take expression trees.
The compiler can automatically compile expression lambdas, but not statement lambdas, into expression trees.
Your second example tries to pass a statement lambda as an Expression(Of Func(Of T, Boolean))
, but the compiler can't do that.
This is stated in section 11.1 of the VB.NET 10 Language Specification:
The exact translation between lambda methods and expression trees may not be fixed between versions of the compiler and is beyond the scope of this specification. For Microsoft Visual Basic 10.0, all lambda expressions may be converted to expression trees subject to the following restrictions:
- Only single-line lambda expressions without ByRef parameters may be converted to expression trees. Of the single-line Sub lambdas, only invocation statements may be converted to expression trees.
- Anonymous type expressions cannot be converted to expression trees if an earlier field initializer is used to initialize a subsequent field initializer, e.g. New With {.a=1, .b=.a}
- Object initializer expressions cannot be converted to expression trees if a member of the current object being initialized is used in one of the field initializers, e.g. New C1 With {.a=1, .b=.Method1()}
- Multi-dimensional array creation expressions can only be converted to expression trees if they declare their element type explicitly.
- Late-binding expressions cannot be converted to expression trees.
- When a variable or field is passed ByRef to an invocation expression but does not have exactly the same type as the ByRef parameter, or when a property is passed ByRef, normal VB semantics are that a copy of the argument is passed ByRef and its final value is then copied back into the variable or field or property. In expression trees, the copy-back does not happen.
All these restrictions apply to nested lambda expressions as well.
It is the restriction in the first item that you are running into. The introduction leaves plenty room to assume that this will be worked on in future releases, there's much to be gained of course. Connect.microsoft.com is a good place to go to encourage them. I couldn't check if a feedback item was already opened for this, the site is on the fritz right now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With