【问题标题】:LINQ execution flow (homework)LINQ 执行流程(作业)
【发布时间】:2019-05-16 07:45:22
【问题描述】:

我不明白以下代码中的执行顺序。这里满足第一个 Where 子句的数字是 (4, 10, 3, 7),满足第二个 Where 子句的数字是 2 和 1,然后我们有函数 Aggregate 减去它们和从两者中制作一个元素。

我的问题是这里的执行流程是什么 - (1) Where 以 c/3 > 0 对所有元素执行,然后 (2) Where 或 (1) 第一个子句执行一个元素及其传递给 (2) 并从那里聚合 - 当我打印值时,我无法使用两种方法在纸上将 x 的值设为 28,我也无法调试 linq 语句。感谢您提前提供任何帮助。

var ints = new int[] { 2, 4, 1, 10, 3, 7 };

var x = ints
    .Where(c => c / 3 > 0)               <-- (1)
    .Select(s2 => s2 + ints
        .Where(c => c / 3 == 0)          <-- (2)
        .Aggregate((f, s) => f - s))     
    .Sum();

【问题讨论】:

  • “我无法调试 linq 语句” - 是的,你可以。如果断点难以遵循,您可以将 lambdas (c =&gt; ...) 制作成代码块 (c =&gt; { ... }) 并添加调试输出 (Debug.WriteLine)。
  • @Sinatr 它不允许我把 { } 括号放在你说的地方......顺便说一句,它不难理解它只是一步执行,或者它允许我只在选择上放置断点以及它没有帮助的变量。
  • @BorisBorovski 来自@Sinatr 的括号如c =&gt; {…} 应写为c =&gt; { return …}
  • @Rafalon 谢谢。但是我仍然没有在第一步(1)第 4 步中得到它,在第二步(2)第 2 步中,因为 2/3 == 0 并且聚合必须执行 4 - 2 但我的逻辑不正确,你能解释一下吗.
  • @BorisBorovski Second 选择 2 和 1,然后对这两个执行聚合:2-1 = 1(请查看下面的答案)

标签: c# linq


【解决方案1】:

同样的语句可以写成如下:

var ints = new int[] { 2, 4, 1, 10, 3, 7 };

var x = ints
    .Where(c =>
        {
            Console.WriteLine($"1 Where for number: {c}");
            return c / 3 > 0;
        }) //< --(1)
    .Select(s2 => s2 + ints
        .Where(c =>
        {
            Console.WriteLine($"2 Where for number: {c}");
            return c / 3 == 0;
        }) // < --(2)
        .Aggregate((f, s) =>
        {
            Console.WriteLine($"Aggregate: f: {f} s: {s}");
            return f - s;
        }))
    .Sum();

在这种情况下,每个速记 lambda 表达式都可以写成带有方法体的完整匿名方法。您只需要使用 { .. } 括号。在它们里面你可以写多个语句。如果您查看Where 的文档,您会发现它需要(在您的情况下)Func&lt;int, bool&gt; 作为输入参数。这意味着您在内部传递一个int返回一个bool。这就是为什么您需要像我一样编写显式返回语句:return c / 3 &gt; 0;

如果您现在将调试输出插入控制台,您将获得书面证明并深入了解整个代码隔间的执行情况。

生成的输出如下所示:

1 Where for number: 2 1 Where for number: 4 2 Where for number: 2 2 Where for number: 4 2 Where for number: 1 Aggregate: f: 2 s: 1 2 Where for number: 10 2 Where for number: 3 2 Where for number: 7 1 Where for number: 1 1 Where for number: 10 2 Where for number: 2 2 Where for number: 4 2 Where for number: 1 Aggregate: f: 2 s: 1 2 Where for number: 10 2 Where for number: 3 2 Where for number: 7 1 Where for number: 3 2 Where for number: 2 2 Where for number: 4 2 Where for number: 1 Aggregate: f: 2 s: 1 2 Where for number: 10 .... ....

【讨论】:

    【解决方案2】:
    ints
        .Where(c => c / 3 == 0)     // (2,1)
        .Aggregate((f, s) => f - s) //  2-1
    

    计算为 1

    因此您的查询可以切换到:

    var ints = new int[] { 2, 4, 1, 10, 3, 7 };
    
    var x = ints
        .Where(c => c / 3 > 0) // (4,10,3,7)
        .Select(s2 => s2 + 1)  // (5,11,4,8)
        .Sum();                // 28
    

    【讨论】:

    • 非常感谢你们。顺便说一句@Mong Zhu,我没有意识到这是让 LINQ 更清晰的匿名方法,也许我必须开始深入阅读文档。
    • 是的,现在它是有道理的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    相关资源
    最近更新 更多