Следующие выражения Lambda и Linq эквивалентны? - PullRequest
1 голос
/ 06 июня 2009

Следующие выражения Lambda и Linq эквивалентны с точки зрения путей выполнения? Я думаю, мне интересно, собирается ли Linq работать по-другому, потому что он собирается создать IEnumerable, прежде чем определять, есть ли в перечислении что-либо, тогда как лямбда-выражение остановится на первой найденной цифре.

var x = valueToMatch
    .Any(c => Char.IsDigit(c));

var y = (from c in valueToMatch
         select c).Any(c => Char.IsDigit(c)); here

Thx! Joel

Ответы [ 3 ]

3 голосов
/ 06 июня 2009

Он будет работать по-другому, но не в значительной степени. Если вы используете MSIL Disassembler , вы увидите несколько отличные выходные данные для первого выражения и второго даже при включенной оптимизации. Вы также можете посмотреть на него, используя Reflector (который немного легче читать).

Вторая версия в основном пропускает каждый элемент через что-то вроде:

[CompilerGenerated]
private static char <Match2>b__2(char c)
{
    return c;
}

перед выполнением выражения Any (c => Char.IsDigit (c)). Так что разница действительно есть.

Однако, разница, на мой взгляд, очень мала. Тестирование списка из 10000 символов, зацикленных на 10000000, при каждом методе первый такт составляет около 125 мс, а второй - 185 мс.

1 голос
/ 06 июня 2009

Они примерно эквивалентны. Компилятор, вероятно, оптимизирует выбор, и оба будут на 100% идентичны. При любой скорости Linq оценивается лениво, поэтому valueToMatch будет перечислять точно одинаковое количество в обоих случаях.

0 голосов
/ 06 июня 2009

Для выражений запроса это представляет собой функцию идентификации :

from c in valueToMatch select c

Это означает, что результат выражения будет точно равен входному значению matchToValue. Поэтому приведенные вами примеры семантически эквивалентны.

В случае выбора без идентификации, например:

from c in valueToMatch select c + ";"

создается IEnumerable<char>, который, при перечислении , будет использовать содержимое valueToMatch и изменять его.

Этот звонок:

(from c in valueToMatch select c + ";").Any(c => Char.IsDigit(c))

перечисляет внутренний запрос, пока не найдет совпадение. Как видите, независимо от исходного запроса он не будет выполняться до вызова Any. Экземпляр IEnumerable<char> представляет возможность запуска запроса, а не запроса, который уже был выполнен. Эта концепция известна как отложенное выполнение .

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