代码相当于链式LINQ扩展方法调用中的'let'关键字

LBu*_*kin 186 c# linq extension-methods linq-to-objects

使用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; 
Run Code Online (Sandbox Code Playgroud)

在上面的查询表达式中,let关键字允许将值传递给where和orderby操作,而无需重复调用animalName.Length.

什么是LINQ扩展方法调用的等效集合,它实现了"let"关键字在这里的作用?

Mar*_*ell 243

让我们没有自己的操作; 它背负着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);
Run Code Online (Sandbox Code Playgroud)

  • 您还可以使用LinqPad结果窗格中的小"lambda"按钮查看生成的代码*if*以Queryable开头.换句话说,如果你将第一行更改为var names = new string [] {"Dog",...} .AsQueryable(); 然后在LinqPad中运行整个事情,单击小lambda按钮,您将看到生成的代码几乎与Marc的答案相同. (19认同)
  • 哇,我不知道你可以使用像这样的新运算符自动封装. (4认同)
  • 我需要在LinqPad中使用`.Dump()`扩展方法来查看生成的lambda. (3认同)

Kel*_*tex 87

有一个很好的文章在这里

基本上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);
Run Code Online (Sandbox Code Playgroud)


Reb*_*bin 7

System.Interactive中还有一个.Let扩展方法,但其目的是引入一个lambda表达式,以便在流畅的表达式中"在线"进行求值.例如,考虑(在LinqPad中,例如)以下表达式,每次执行时都会创建新的随机数:

var seq = EnumerableEx.Generate(
    new Random(),
    _ => true,
    _ => _,
    x => x.Next());
Run Code Online (Sandbox Code Playgroud)

要查看每次出现的新随机样本,请考虑以下内容

seq.Zip(seq, Tuple.Create).Take(3).Dump();
Run Code Online (Sandbox Code Playgroud)

它产生左右不同的对.要生成左侧和右侧始终相同的对,请执行以下操作:

seq.Take(3).ToList().Let(xs => xs.Zip(xs, Tuple.Create)).Dump(); 
Run Code Online (Sandbox Code Playgroud)

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

(xs => xs.Zip(xs, Tuple.Create))(seq.Take(3).ToList()).Dump();
Run Code Online (Sandbox Code Playgroud)

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