Код, эквивалентный ключевому слову 'let' в цепочке вызовов метода LINQ
Используя функции компилятора С# для компиляции запросов, вы можете написать код, например:
var names = new string[] { "Dog", "Cat", "Giraffe", "Monkey", "Tortoise" };
var result =
from animalName in names
let nameLength = animalName.Length
where nameLength > 3
orderby nameLength
select animalName;
В выражении запроса выше ключевое слово let
позволяет передать значение в операции where и orderby без дублирования вызовов animalName.Length
.
Что такое эквивалентный набор вызовов метода расширения LINQ, который достигает того, что здесь делает ключевое слово "let"?
Ответы
Ответ 1
Пусть не имеет собственной операции; он копирует от Select
. Вы можете увидеть это, если вы используете "рефлектор", чтобы разделить существующую dll.
это будет что-то вроде:
var result = names
.Select(animalName => new { nameLength = animalName.Length, animalName})
.Where(x=>x.nameLength > 3)
.OrderBy(x=>x.nameLength)
.Select(x=>x.animalName);
Ответ 2
Там хорошая статья здесь
По существу let
создает анонимный кортеж. Это эквивалентно:
var result = names.Select(
animal => new { animal = animal, nameLength = animal.Length })
.Where(x => x.nameLength > 3)
.OrderBy(y => y.nameLength)
.Select(z => z.animal);
Ответ 3
Существует также метод расширения .Let в System.Interactive, но его цель - ввести лямбда-выражение, которое должно быть оценено "in-line" в свободно выраженном выражении. Например, рассмотрите (в LinqPad, скажем) следующее выражение, которое создает новые случайные числа каждый раз, когда он выполняется:
var seq = EnumerableEx.Generate(
new Random(),
_ => true,
_ => _,
x => x.Next());
Чтобы увидеть, что новые случайные выборки появляются каждый раз, рассмотрим следующие
seq.Zip(seq, Tuple.Create).Take(3).Dump();
который создает пары, в которых слева и справа разные. Для создания пар, в которых слева и справа всегда одно и то же, сделайте следующее:
seq.Take(3).ToList().Let(xs => xs.Zip(xs, Tuple.Create)).Dump();
Если бы мы могли напрямую ссылаться на лямбда-выражения, мы могли бы написать
(xs => xs.Zip(xs, Tuple.Create))(seq.Take(3).ToList()).Dump();
Но мы не можем вызывать лямбда-выражения, как если бы они были методами.
Ответ 4
о коде, эквивалентном ключевому слову let в вызовах метода расширения LINQ
вышеуказанный комментарий больше не действителен
var x = new List<int> { 2, 3, 4, 5, 6 }.AsQueryable();
(from val in x
let val1 = val
let val2 = val + 1
where val2 > val1
select val
).Dump();
производит
System.Collections.Generic.List'1[System.Int32]
.Select(
val =>
new
{
val = val,
val1 = val
}
)
.Select(
temp0 =>
new
{
temp0 = temp0,
val2 = (temp0.val + 1)
}
)
.Where(temp1 => (temp1.val2 > temp1.temp0.val1))
.Select(temp1 => temp1.temp0.val)
так что несколько let
оптимизируются сейчас