Linq:执行链查询顺序
Linq: Order of execution chain query
我想了解链查询是如何处理的。例如,让我们考虑以下查询
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()
其中 returns(让我们用)IEnum0
实例
IEnum0
调用 GetEnumerator()
其中 returns IEnum1
实例
IEnum1
调用 GetEnumerator()
其中 returns IEnum2
实例
IEnum2
调用 GetEnumerator()
其中 returns IEnum3
实例
2。调用 MoveNext(向后传递)
.Sum()
在 IEnum3
上调用 MoveNext()
IEnum3
在 IEnum2
上调用 MoveNext()
IEnum2
在 IEnum1
调用 MoveNext()
IEnum1
在 IEnum0
调用 MoveNext()
3。从 MoveNext 返回(前向-后向传递)
IEnum0
移动到元素 -1
和 return true
.
IEnum1
检查 -1
是否满足条件(这不是真的)所以 IEnum1
在 IEnum0
. 上调用 MoveNext()
IEnum0
移动到元素 4
和 return true
.
IEnum1
检查 4
是否满足条件(为真)和 returns true
IEnum2
什么都不做,只是 return IEnum1
的输出,即 true
IEnum2
什么都不做,只是 IEnum2
的 return 输出,即 true
4.调用当前(向后传递)
.Sum()
在 IEnum3
上调用 Current
。
IEnum3
在 IEnum2
上调用 Current
IEnum2
在 IEnum1
调用 Current
IEnum1
在 IEnum0
上调用 Current
5.返回电流(正向通过)
IEnum0
returns 4
IEnum1
returns 4
IEnum2
returns sqrt(4)=2
IEnum3
returns exp(2)
6.重复步骤 2.-5。直到第 3 步。returns false
如果以不同的方式处理链查询,请纠正我。
您可以使用委托来了解执行顺序。示例:
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
我想了解链查询是如何处理的。例如,让我们考虑以下查询
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()
其中 returns(让我们用)IEnum0
实例IEnum0
调用GetEnumerator()
其中 returnsIEnum1
实例IEnum1
调用GetEnumerator()
其中 returnsIEnum2
实例IEnum2
调用GetEnumerator()
其中 returnsIEnum3
实例
2。调用 MoveNext(向后传递)
.Sum()
在IEnum3
上调用 IEnum3
在IEnum2
上调用 IEnum2
在IEnum1
调用 IEnum1
在IEnum0
调用
MoveNext()
MoveNext()
MoveNext()
MoveNext()
3。从 MoveNext 返回(前向-后向传递)
IEnum0
移动到元素-1
和 returntrue
.IEnum1
检查-1
是否满足条件(这不是真的)所以IEnum1
在IEnum0
. 上调用 IEnum0
移动到元素4
和 returntrue
.IEnum1
检查4
是否满足条件(为真)和 returnstrue
IEnum2
什么都不做,只是 returnIEnum1
的输出,即true
IEnum2
什么都不做,只是IEnum2
的 return 输出,即true
MoveNext()
4.调用当前(向后传递)
.Sum()
在IEnum3
上调用Current
。IEnum3
在IEnum2
上调用 IEnum2
在IEnum1
调用 IEnum1
在IEnum0
上调用
Current
Current
Current
5.返回电流(正向通过)
IEnum0
returns4
IEnum1
returns4
IEnum2
returnssqrt(4)=2
IEnum3
returnsexp(2)
6.重复步骤 2.-5。直到第 3 步。returns false
如果以不同的方式处理链查询,请纠正我。
您可以使用委托来了解执行顺序。示例:
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