Why does ReSharper tell me “implicitly captured closure”?

前端 未结 5 1813
我在风中等你
我在风中等你 2020-12-04 06:20

I have the following code:

public double CalculateDailyProjectPullForceMax(DateTime date, string start = null, string end = null)
{
    Log(\"Calculating Dai         


        
5条回答
  •  醉梦人生
    2020-12-04 06:43

    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:

    • instance methods representing the lambdas
    • fields representing all values captured by any of those lambdas

    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.Lambda1
    • callable2 does not keep a reference to its argument, helper.Lambda2

    In 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.

提交回复
热议问题