Linq:执行链查询的顺序

时间:2018-08-09 10:10:59

标签: 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()MoveNext()上呼叫IEnum3
  • IEnum3MoveNext()上呼叫IEnum2
  • IEnum2MoveNext()上呼叫IEnum1
  • IEnum1MoveNext()上呼叫IEnum0

3。从MoveNext返回(前进后退)

  • IEnum0移至元素-1并返回true
  • IEnum1检查-1是否满足条件(不是真的),因此IEnum1MoveNext()上调用IEnum0
  • IEnum0移至元素4并返回true
  • IEnum1检查4是否满足条件(正确)并返回true
  • IEnum2不执行任何操作,仅返回IEnum1的输出true
  • IEnum2不执行任何操作,仅返回IEnum2的输出true

4。呼叫当前(向后传递)

  • .Sum()Current上呼叫IEnum3
  • IEnum3Current上呼叫IEnum2
  • IEnum2Current上呼叫IEnum1
  • IEnum1Current上呼叫IEnum0

5。返回电流(前进)

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

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

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

1 个答案:

答案 0 :(得分:9)

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

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:错误

     

4> 0:是

     

Math.Sqrt(4):2

     

Math.Exp(2):7.38905609893065

     

SumNumber(7.38905609893065)

     

9> 0:是

     

Math.Sqrt(9):3

     

Math.Exp(3):20.0855369231877

     

SumNumber(20.0855369231877)

     

sumOfRoots = 27.4745930221183