C# 与';让';链接LINQ扩展方法调用中的关键字

C# 与';让';链接LINQ扩展方法调用中的关键字,c#,linq,extension-methods,linq-to-objects,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 animal

使用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

实现“let”关键字在这里所做的功能的LINQ扩展方法调用的等效集合是什么?

有一篇好文章

本质上,让创建一个匿名元组。这相当于:

var result = names.Select(
  animal => new { animal = animal, nameLength = animal.Length })
.Where(x => x.nameLength > 3)
.OrderBy(y => y.nameLength)
.Select(z => z.animal);

让我们不要有自己的操作;它借助于
选择
。如果您使用“reflector”来分离现有的dll,您可以看到这一点

它将类似于:


System.Interactive中还有一个.Let扩展方法,但它的目的是引入一个lambda表达式,以便在fluent表达式中“在线”计算。例如,考虑(在LinqPad,说)下面的表达式,每次执行时都创建新的随机数:

var seq = EnumerableEx.Generate(
    new Random(),
    _ => true,
    _ => _,
    x => x.Next());
<> P>为了发现新的随机样本每次出现,请考虑下面的

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表达式。

about

上述评论不再有效

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();

因此,现在对多个
let
进行了优化

FYI,C#3.0规范以极其详细的方式解释了每个查询理解翻译规则。对于那些认为规范很难理解的人,Jon Skeet的C#Depth也涵盖了它-p C#语言规范是可下载的Word文档,其内容未被搜索引擎索引,既不可链接也不可在线浏览。如果规范可以在线获得,那将是一个很大的帮助。哇,我不知道你可以使用新的操作符那样自动封装。如果你从一个可查询的开始,你也可以使用LinqPad结果窗格中的小“lambda”按钮来查看生成的代码。换句话说,如果将第一行更改为var names=newstring[]{“Dog”,…}.AsQueryable();然后在LinqPad中运行整个程序,单击小lambda按钮,您将看到生成的代码与Marc的答案几乎相同在LinqPad中使用扩展方法来查看生成的lambda。我引用了上面的文章
在不需要转换变量的情况下,建议不要使用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)