Reputation: 1028
I want to understand how chain query is processed. For example, let us consider the following query
var sumOfRoots = numbers //IEnum0
.Where(x => x > 0) //IEnum1
.Select(x => Math.Sqrt(x)) //IEnum2
.Select(x => Math.Exp(x)) //IEnum3
.Sum();
where e.g. numbers={-1, 4, 9 }.
Is this what happends behind the scene:
1. Getting all enumerators (forward pass)
numbers
calls GetEnumerator()
which returns (let us denote it with) IEnum0
instanceIEnum0
calls GetEnumerator()
which returns IEnum1
instanceIEnum1
calls GetEnumerator()
which returns IEnum2
instanceIEnum2
calls GetEnumerator()
which returns IEnum3
instance2. Calling MoveNext (backward pass)
.Sum()
calls MoveNext()
on IEnum3
IEnum3
calls MoveNext()
on IEnum2
IEnum2
calls MoveNext()
on IEnum1
IEnum1
calls MoveNext()
on IEnum0
3. Returning from MoveNext (forward-backward pass)
IEnum0
moves to element -1
and return true
.IEnum1
check if -1
satisfy condition (which is not true) so IEnum1
calls MoveNext()
on IEnum0
.IEnum0
moves to element 4
and return true
.IEnum1
check if 4
satisfy condition (which is true) and returns true
IEnum2
does nothing, just return output of IEnum1
which is true
IEnum2
does nothing, just return output of IEnum2
which is true
4. Calling Current (backward pass)
.Sum()
calls Current
on IEnum3
.IEnum3
calls Current
on IEnum2
IEnum2
calls Current
on IEnum1
IEnum1
calls Current
on IEnum0
5. Returning Current (forward pass)
IEnum0
returns 4
IEnum1
returns 4
IEnum2
returns sqrt(4)=2
IEnum3
returns exp(2)
6. Repeat steps 2.-5. until step 3. returns false
Please correct me if a chain query is processed in a different way.
Upvotes: 8
Views: 898
Reputation: 18179
You can use delegates to understand the order of execution. Example:
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;
}
Output:
-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
Upvotes: 11