c# - Linq:执行链查询顺序

标签 c# linq ienumerable ienumerator

我想了解链式查询是如何处理的。例如,让我们考虑以下查询

var sumOfRoots = numbers           //IEnum0
     .Where(x => x > 0)            //IEnum1
     .Select(x => Math.Sqrt(x))    //IEnum2
     .Select(x => Math.Exp(x))     //IEnum3
     .Sum();

例如numbers={-1, 4, 9 }.

这是幕后发生的事情吗:

<强>1。获取所有枚举器(前向传递)

  • numbers 调用 GetEnumerator() 返回(让我们用它表示)IEnum0 实例
  • IEnum0 调用 GetEnumerator() 返回 IEnum1 实例
  • IEnum1 调用 GetEnumerator() 返回 IEnum2 实例
  • IEnum2 调用 GetEnumerator() 返回 IEnum3 实例

<强>2。调用 MoveNext(向后传递)

  • .Sum()IEnum3
  • 上调用 MoveNext()
  • IEnum3IEnum2
  • 上调用 MoveNext()
  • IEnum2IEnum1
  • 上调用 MoveNext()
  • IEnum1IEnum0
  • 上调用 MoveNext()

<强>3。从 MoveNext 返回(前向-后向传递)

  • IEnum0 移动到元素 -1 并返回 true
  • IEnum1 检查 -1 是否满足条件(这不是真的)所以 IEnum1 调用 MoveNext()IEnum0 上。
  • IEnum0 移动到元素 4 并返回 true
  • IEnum1 检查 4 是否满足条件(为真)并返回 true
  • IEnum2 什么都不做,只是返回 IEnum1 的输出,它是 true
  • IEnum2 什么也不做,只是返回 IEnum2 的输出,它是 true

<强>4。调用电流(向后传递)

  • .Sum()IEnum3 上调用 Current
  • IEnum3IEnum2
  • 上调用 Current
  • IEnum2IEnum1
  • 上调用 Current
  • IEnum1IEnum0
  • 上调用 Current

<强>5。返回电流(正向通过)

  • IEnum0 返回 4
  • IEnum1 返回 4
  • IEnum2 返回 sqrt(4)=2
  • IEnum3 返回 exp(2)

6.重复步骤 2.-5。直到第 3 步。返回 false

如果以不同的方式处理链查询,请纠正我。

最佳答案

您可以使用委托(delegate)来了解执行顺序。示例:

static void Main(string[] args)
{
    var numbers = new []{ -1, 4, 9 };

    double sumOfRoots = numbers.Where(IsGreaterThanZero)   
                               .Select(ToSquareRoot)      
                               .Select(ToExp)              
                               .Sum(x => ToNumber(x));

    Console.WriteLine($"sumOfRoots = {sumOfRoots}");

    Console.Read();
}

private static double ToNumber(double number)
{
    Console.WriteLine($"SumNumber({number})");

    return number;
}

private static double ToSquareRoot(int number)
{
    double value =  Math.Sqrt(number);

    Console.WriteLine($"Math.Sqrt({number}): {value}");

    return value;
}

private static double ToExp(double number)
{
    double value =  Math.Exp(number);

    Console.WriteLine($"Math.Exp({number}): {value}");

    return value;
}

private static bool IsGreaterThanZero(int number)
{
    bool isGreater = number > 0;

    Console.WriteLine($"{number} > 0: {isGreater}");

    return isGreater;
}

输出:

-1 > 0: False

4 > 0: True

Math.Sqrt(4): 2

Math.Exp(2): 7.38905609893065

SumNumber(7.38905609893065)

9 > 0: True

Math.Sqrt(9): 3

Math.Exp(3): 20.0855369231877

SumNumber(20.0855369231877)

sumOfRoots = 27.4745930221183

关于c# - Linq:执行链查询顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51764310/

相关文章:

c# - 通过 LINQ 将表达式树应用于 List

c# - 将查询投影到匿名 Dictionary<string,int>

c# - 无法将类型 'System.Collections.Generic.List<String>' 隐式转换为 'System.Collections.Generic.IEnumerable<turon.Model.Products_Products>

c# - 通知列表 wpf .net4.0 中的更改

c# - 加密异常 : Key not valid for use in specified state

c# - 仅从 DataGridView 的特定列获取文本

java - LINQ for Java 工具

c# - Linq to SQL、InsertOnSubmit 与 InsertAllOnSubmit 性能对比?

c# - IEnumerable<T> 与 T[]

c# - 我怎样才能使我产生的 IEnumerable 与 PagedList 一起工作