I have been trying to cache the results of certain Actions
and Funcs
.
For that purpose I am storing the Actions
/Funcs
in a Dictionary
with their respective result.
Whilst doing this I stumbled upon something unexpected (example is simplified):
var lstActions = new List<Action>();
for (int i = 0; i < 2; i++)
{
lstActions.Add(() => { });
}
bool bEqual = lstActions[0] == lstActions[1]; // Result = true
--
var lstActions = new List<Action>();
lstActions.Add(() => { });
lstActions.Add(() => { });
bool bEqual = lstActions[0] == lstActions[1]; // Result = false
Can anyone explain why the results are different?
答案 0 :(得分:2)
You're seeing implementation details about how the compiler transforms lambda expressions into delegates that point to compiler-generated methods.
This behavior may change due to changes in the compiler, debug vs. release builds, or changes in the contents of any of the lambdas.
To explain your current behavior:
Every lambda that appears in source is compiled to a separate method. Therefore, your second example generates two methods (which happen to have identical bodies), and the delegates are not the same.
Your first example only has one lambda in the source, so it compiles to a single method. Because the lambda doesn't use any local variables, it doesn't generate a closure class, so the both the Method
and Target
properties of the delegates are the same.
答案 1 :(得分:0)
The compiler tries to minimize the amount of delegate
objects it creates. To this end it often caches instances where this is possible.
Since your first example you define a single lambda and it does not capture any loop variables, a single delegate instance will suffice.
In the second example, you defined two different anonymous methods, the compiler will not check that their code is identical as this is a rare case, and will create two delegate instances.
This is however an implementation detail of the compiler and I would not rely on it in any way.