【问题标题】:How do you read lambda expressions?你如何阅读 lambda 表达式?
【发布时间】:2011-06-20 14:53:48
【问题描述】:

我一直在尝试弄清楚为什么 lambda 表达式对我来说还不够直观。 我怀疑部分原因可能是因为当我浏览代码时,我有时会在内部将其翻译成我的母语,以便我自己清楚。 例如:

endDate.Value = someNullableDate ?? (object)DBNull.Value;
// I could read as:
set endDate to someNullableDate or, if null, to (object)dbNull

另一种语言的例子:

for(int count = 0; count >= 42; count++) {
    cout << "Count is " << count << endl;
}
// May read as:
from an integer "count" as zero to 42 inclusive, display "Count is " and then the integer.

那么如何读取 lambda 表达式:

var myList = new List<String>(/* various string values */);
var foo = myList.Select(s => s.Trim()).ToList(); //?

【问题讨论】:

标签: c# .net lambda


【解决方案1】:

我会这样理解:

从中单独选择每个项目 myList 变成一个变量 s,使用 s, 在其上应用 Trim() 并完成 与 myList 中的所有项目,转换 整个事情都列在一个列表中。

【讨论】:

  • “一旦完成” - 不是。 While doing so 将它们收集到一个列表中以供将来参考(参见Lazy/Deferred Evaluation
  • ToList() 仅在投影到 IEnumerable 之后执行,对吗?投影发生在 Select 语句期间,然后“一旦完成”,所有项目都通过使用 ToList() 枚举。还是你的意思是别的?
  • 不; 'ToList() 仅在投影后 完成 ...';微妙但真实的区别。您的版本意味着两个枚举(这不适用于某些可枚举,或不支持 Reset() 的枚举器或像Directory.EnumerateFiles Method 这样昂贵的枚举器)
  • 据我所知,我只是暗示在 ToList() 期间发生的一个枚举。您是说 ToList() 在 Select 操作期间起作用吗?如果是这样,我不知道这一点。
  • 确实如此。或者,相反,情况正好相反。 C#iterator blocks (think: yield) 导致技术上称为协同过程:实际上(部分)选择在 ToList() 的枚举器循环的每次迭代中执行一次。无论迭代器块多么复杂,即使它不是有限的,这也成立。使用调试器逐步完成一个惰性可枚举的手写 for-each 循环,您将看到它实际上是如何工作的!
【解决方案2】:

鉴于 LINQ 通常只适用于 IEnumerable 对象,您可以将 s =&gt; 读作“对于 IEnumerable 中的每个 s”。

更新: 5年后重新审视这个答案,我对此深感不满意。就个人而言,现在我发现自己认为它是“映射到”或者我已经看到“这样的”,这也取决于具体情况。

【讨论】:

  • for each 在这种情况下似乎非常适用。您能否详细说明在这种情况下您将如何应用“地图”或“这样”的概念?
【解决方案3】:

前几次,您需要将完整的表达式分解为位并将它们转换为您熟悉的语法,最终您将熟悉 lambda。

在这个sn-p中,

var foo = myList.Select(s => s.Trim()).ToList();

Select() 做的投影操作与sql中的类似。

s =&gt; s.Trim()可以转换成

string SomeMethod(string input)
{
    return input.Trim();
}

最后一个ToList() 是一个将IEnumerable&lt;T&gt; 转换为List&lt;T&gt; 的扩展方法。

【讨论】:

  • +1 但对 SQL 的引用比解释更令人困惑和偏离
【解决方案4】:

我不是用英文读的。这有点像说一门外语。一旦你真正掌握了它,你就不会来回使用你的母语来使用它。

虽然我可以将它翻译成英文,但这种尝试似乎破坏了未翻译代码的含义。 (即“将 foo 设置为 myList 中修剪值的列表。”)

【讨论】:

  • “一旦你真正掌握了它,你就不会来回回到你的母语来使用它。”说得好。 +1
【解决方案5】:

类似的东西:

从 myList 中,修剪每个字符串 "s" 并将其放入一个新列表中

【讨论】:

    【解决方案6】:

    对于 myList 中的每个 String 项目,对该项目执行Trim(),然后将结果作为列表返回。

    请参阅Enumerable.Select 上的文档。它本质上是一个内置的 foreach,能够在处理完结果后返回结果。

    【讨论】:

      【解决方案7】:

      我在学习 C# 时写了最初的问题,现在发现 LINQ 非常直观。

      我阅读了我的原始代码:

      var foo = myList.Select(s => s.Trim()).ToList(); //?
      

      作为:

      For each string "s" in myList, trim "s", then ToList() the results.
      

      今天我不会使用 LINQ 来完成这项任务。从根本上说,它是一种查询语言(LINQ 中的 Q),不一定是修改列表的最有效选择。 如果我仍然选择 LINQ,我会使用它的 .ForEach() 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-08
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        相关资源
        最近更新 更多