I have the following code:
public double CalculateDailyProjectPullForceMax(DateTime date, string start = null, string end = null)
{
Log(\"Calculating Dai
The warning is valid and displayed in methods that have more than one lambda, and they capture different values.
When a method that contains lambdas is invoked, a compiler-generated object is instantiated with:
As an example:
class DecompileMe
{
DecompileMe(Action callable1, Action callable2)
{
var p1 = 1;
var p2 = "hello";
callable1(() => p1++); // WARNING: Implicitly captured closure: p2
callable2(() => { p2.ToString(); p1++; });
}
}
Examine the generated code for this class (tidied up a little):
class DecompileMe
{
DecompileMe(Action callable1, Action callable2)
{
var helper = new LambdaHelper();
helper.p1 = 1;
helper.p2 = "hello";
callable1(helper.Lambda1);
callable2(helper.Lambda2);
}
[CompilerGenerated]
private sealed class LambdaHelper
{
public int p1;
public string p2;
public void Lambda1() { ++p1; }
public void Lambda2() { p2.ToString(); ++p1; }
}
}
Note the instance of LambdaHelper created stores both p1 and p2.
Imagine that:
callable1 keeps a long-lived reference to its argument, helper.Lambda1callable2 does not keep a reference to its argument, helper.Lambda2In this situation, the reference to helper.Lambda1 also indirectly references the string in p2, and this means that the garbage collector will not be able to deallocate it. At worst it is a memory/resource leak. Alternatively it may keep object(s) alive longer than otherwise needed, which can have an impact on GC if they get promoted from gen0 to gen1.