Anonymous Methods and Captures in VCL

Anonymous Methods and Captures in VCL

Found an interesting debugging effect of captures today.  

Picture a frame with a list and a MyValueEdit (TAdvSpinEdit to be exact).  So, I’d made a bad decision to check the MyValueEdit.FloatValue in an anon method which was looped for selected elements in the list. 

Firstly, the value was wrong.  Even though I believed I had edited the value before the loop – the captured MyValueEdit retained the original value.

Secondly, trying to inspect MyValueEdit inside the anon method, informed me rather sternly that “MyValueEdit” is unknown.

Note to self: When in an anonymous method, minimize references to local variables outside the method. Needless to say, I am also looking at doing a proper enumerator instead of a loop that takes an anon method.

9 thoughts on “Anonymous Methods and Captures in VCL

  1. ‘Even though I believed I had edited the value before the loop – the captured MyValueEdit retained the original value’ – that doesn’t sound right given the value in itself shouldn’t be copied either way. Do you have some sharable code that demonstrates this…?

  2. It’s just too much library code to extract an example.  I intend to try to recreate in a small scale, but it’s test focus days before a new pilot rollout – so no time to spend on it until next week.  My colleague did debug the code on two different Delphi installations before he passed on the problem to me.  Trying to inspect the variable was not possible, and although I am not certain that it was related – a core ide dll bombed out the BDS shortly after.

  3. AFAIK, you’re limited in terms of what you can access within an anon method. Specifically, you can refer to local stack variables of the enclosing method, but you cannot access objects outside of that. And there may be restrictions in terms of the complexity of local variables as well. As you have found, you need to copy values from objects on the form into a local variable in the enclosing scope before the anon method is called in order to see them. This is not unique to Delphi.

  4. +David You can access a lot more than that. You aren’t limited just to what can be captured. As far as capture goes it must be a variable that is created in the local scope so that it can be lifted to a wider scope.

  5. +DH It sounds like you’re saying that what he encountered should work. But it doesn’t. Captured variables need to be local, which is what I said (or was implying, anyway). As far as “lifting to a wider scope”, I’m not sure how you can do that when the object you want to access is something like a TEdit on a form. Such objects exist outside the scope of the anonymous method. You have to access the object, or at least its contents, indirectly, say through some kind of injection. While I’ve messed around with this a bit, I know there’s stuff that works and stuff that doesn’t. I don’t have a clear map of the entire set of boundaries in my head yet, but this is what I’ve found works most consistently.

  6. David Schwartz Captured variables need to be local. I already said that. Lifting to a wider scope, a consequence of capture, is only possible for locals. If the variable was created in an outer scope, it’s too late. I cannot be lifted once it has been created.

    However, anonymous methods can refer to more than just captured locals.

Leave a Reply