205

使用 C# 编译器的查询理解功能,您可以编写如下代码:

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”关键字在此处的作用?

4

4 回答 4

269

Let没有自己的操作;它背负着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);
于 2009-07-07T14:46:00.273 回答
95

这里有一篇好文章

本质上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);
于 2009-07-07T14:39:12.343 回答
7

System.Interactive 中还有一个 .Let 扩展方法,但其目的是引入一个 lambda 表达式,以便在流畅的表达式中“内联”评估。例如,考虑(例如在 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(); 

如果我们可以直接调用 lambda 表达式,我们可以写

(xs => xs.Zip(xs, Tuple.Create))(seq.Take(3).ToList()).Dump();

但是我们不能像调用方法一样调用 lambda 表达式。

于 2011-06-06T18:01:25.493 回答
1

关于在链式 LINQ 扩展方法调用中等效于 'let' 关键字的代码

以上评论不再有效

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现在优化了多个

于 2019-06-21T14:25:50.813 回答