VB.NET: «Ошибка лямбда-выражений не может быть преобразована в деревья выражений» - PullRequest
8 голосов
/ 18 февраля 2011

Почему я могу делать следующее:

Dim qNodes As IQueryable(Of XmlNode) = xDoc.ChildNodes.AsQueryable()
Dim test = qNodes.Where(Function(node) True)

хотя следующее дает ошибку, которую я указал в заголовке:

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

Я действительно не понимаю.

Ответы [ 2 ]

11 голосов
/ 18 февраля 2011

VB.Net поддерживает два вида лямбда-выражений:

  • Выражения лямбда содержат одно выражение и неявно возвращают выражение.
    Например: Function(x) x.ToString()

  • Лямбды операторов содержат одно или несколько операторов и должны явно использовать ключевое слово Return (если они возвращают значение)
    Это новыеVB.Net 2010.
    Например:

    Sub(x)
        Logger.Log(x)
        Console.WriteLine(x)
    End Sub
    

Метод Where и все другие методы IQueryable, принимают деревья выражений .
Компилятор может автоматически скомпилировать выражение лямбда-выражения, но не лямбда-выражения, в деревья выражений.

Ваш второй пример пытается передать оператор лямбда как Expression(Of Func(Of T, Boolean)), но компилятор не может этого сделать.

7 голосов
/ 18 февраля 2011

Это указано в разделе 11.1 спецификации языка VB.NET 10:

Точный перевод между лямбда-методами и деревьями выражений не может быть зафиксирован между версиями компилятора и выходит за рамкиэтой спецификации.В Microsoft Visual Basic 10.0 все лямбда-выражения могут быть преобразованы в деревья выражений с учетом следующих ограничений:

  1. Только однострочные лямбда-выражения без параметров ByRef могут быть преобразованы в деревья выражений.Из однострочных Sub lambdas в деревья выражений могут быть преобразованы только операторы вызова.
  2. Выражения анонимного типа не могут быть преобразованы в деревья выражений, если для инициализации последующего инициализатора поля используется более ранний инициализатор поля, например, New с{.a = 1, .b = .a}
  3. Выражения инициализатора объекта не могут быть преобразованы в деревья выражений, если в одном из инициализаторов поля используется элемент текущего инициализируемого объекта, например New C1 With {.a = 1, .b = .Method1 ()}
  4. Выражения создания многомерного массива можно преобразовать в деревья выражений, только если они явно объявили свой тип элемента.
  5. Выражения с поздним связываниемневозможно преобразовать в деревья выражений.
  6. Когда переменная или поле передаются ByRef в выражение вызова, но не имеют точно такой же тип, как параметр ByRef, или когда свойство передается ByRef, обычная семантика VBчто копия аргумента передается ByRef и ее окончательное значениеen копируется обратно в переменную или поле или свойство.В деревьях выражений обратное копирование не происходит.

Все эти ограничения распространяются и на вложенные лямбда-выражения.

Это ограничение в первом элементе, котороевы сталкиваетесьВступление оставляет много места для предположения, что над этим будут работать в будущих выпусках, конечно же, многое можно получить.Connect.microsoft.com - хорошее место, чтобы поощрить их.Я не мог проверить, был ли открыт элемент обратной связи для этого, сайт сейчас на фритюре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...