✅ Compiler creates closure when it's not necessary?
I have this function here:
And then I'm using it like this:
But I have the "Heap Allocation Viewer" plugin installed in Rider, and it says it allocates a closure for the variable
t
? Even when I run my app, and debug the Run function, it seems to create a hidden class. Why does it do this, even though the Action isn't accessing any variables in the outer scope?22 Replies
apart from
this
?EVen if I don't use a tuple as the parameter, and just pass "this", it still says closure allocation
that's being passed as a parameter, it's not used in the lambda
should the compiler know?
erm, yes?
the compiler does capture analysis to know what to include in the closure
plug that code into sharplab and look at the decompile maybe?
but it's passing through a layer which would be
action(parameter)
Even in release too
oh, I think I see what it's doing
it's caching
look at the invocation line
basically it's making sure the Action is only ever allocated once per the app's life
instead of every time M is called
now look what happens if you make one of them a proper closure https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGAzAATakDCpA3oaQ+WRiqQLIAUGOADKQM4BKWvUZiASgFcAdhwSkAvAD5yOAJwchAGlIAiCAGtdggNyixDKbPnLVGhIJ36jp8xatzFK7vcd7DxmYEYgC+bm4kqkjkrFYAPAAqSlw4WIkqAIZgAC4AlhDSOgmkAA4ZUBkAtjDZMFDCtll5BRxlFdW19UEhQA
SharpLab
C#/VB/F# compiler playground.
also does the same for method groups https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGAzAATakDCpA3oaQ+WRiqQLIAUGOADKQM4BKWvUZiASgFcAdhwSkAvAD5yOAJwchAGlIAiCAGtdggNyixDKbPnLVGhIJ36jp8xatzFK7vcd7DxmYEFowePk4BrsGMAL5ubiSqSOSsVgA8ACpKXDhYmSoAhmAALgCWENI6GaQADgVQBQC2MMUwUMK2RWUVHHUNza3tQTFAA= @carrotther
SharpLab
C#/VB/F# compiler playground.
I guess the plugin is giving the warning for the wrong reason then?
Even in the IL viewer it doesn't seem to create a closure class... probably should have looked at that first
yeah
I get the caching of the action though
becomes
only the first one that captures
s
actually incurs a new allocation on every call of M
the rest are a one-time costThese types of warnings are notoriously hard to get right
Hm in my actual code, it actually does seem to create an instance of one of those DisplayClass things
side note, since you're here @333fred, why are they called display classes?
¯\_(ツ)_/¯
Nvm i was misreading the IL code, It's storing that cached action in a display class instance. newobj only gets called twice at the start, then only once afterwards which is the ValueTuple
At least my attempts to make this app run faster weren't a total waste