Linq:链式查询的执行顺序

问题描述 投票:0回答:1

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

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()
    致电
    MoveNext()
    IEnum3
  • IEnum3
    致电
    MoveNext()
    IEnum2
  • IEnum2
    致电
    MoveNext()
    IEnum1
  • IEnum1
    致电
    MoveNext()
    IEnum0

3.从 MoveNext 返回(前后传递)

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

4。调用Current(向后传递)

  • .Sum()
    Current
    上呼叫
    IEnum3
  • IEnum3
    致电
    Current
    IEnum2
  • IEnum2
    致电
    Current
    IEnum1
  • IEnum1
    致电
    Current
    IEnum0

5。返回电流(正向传递)

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

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

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

c# linq ienumerable ienumerator
1个回答
11
投票

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

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
© www.soinside.com 2019 - 2024. All rights reserved.