13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Captur<strong>in</strong>g variables <strong>in</strong> anonymous methods155ret();return ret;}...ThreadStart x = CreateDelegateInstance();x();x();The output of list<strong>in</strong>g 5.12 consists of the numbers 5, 6, and 7 on separate l<strong>in</strong>es. Thefirst l<strong>in</strong>e of output comes from the <strong>in</strong>vocation of the delegate <strong>in</strong>stance with<strong>in</strong>CreateDelegateInstance, so it makes sense that the value of i is available at thatpo<strong>in</strong>t. But what about after the method has returned? Normally we would considercounter to be on the stack, so when the stack frame for CreateDelegateInstance isdestroyed we’d expect counter to effectively vanish… and yet subsequent <strong>in</strong>vocationsof the returned delegate <strong>in</strong>stance seem to keep us<strong>in</strong>g it!The secret is to challenge the assumption that counter is on the stack <strong>in</strong> the firstplace. It isn’t. The compiler has actually created an extra class to hold the variable.The CreateDelegateInstance method has a reference to an <strong>in</strong>stance of that class so itcan use counter, and the delegate has a reference to the same <strong>in</strong>stance—which liveson the heap <strong>in</strong> the normal way. That <strong>in</strong>stance isn’t eligible for garbage collection untilthe delegate is ready to be collected. Some aspects of anonymous methods are verycompiler specific (<strong>in</strong> other words different compilers could achieve the same semantics<strong>in</strong> different ways), but it’s hard to see how the specified behavior could beachieved without us<strong>in</strong>g an extra class to hold the captured variable. Note that if youonly capture this, no extra types are required—the compiler just creates an <strong>in</strong>stancemethod to act as the delegate’s action.OK, so local variables aren’t always local anymore. You may well be wonder<strong>in</strong>g whatI could possibly throw at you next—let’s see now, how about multiple delegates captur<strong>in</strong>gdifferent <strong>in</strong>stances of the same variable? It sounds crazy, so it’s just the k<strong>in</strong>d ofth<strong>in</strong>g you should be expect<strong>in</strong>g by now.5.5.5 Local variable <strong>in</strong>stantiationsOn a good day, captured variables act exactly the way I expect them to at a glance. Ona bad day, I’m still surprised when I’m not tak<strong>in</strong>g a great deal of care. When there areproblems, it’s almost always due to forgett<strong>in</strong>g just how many “<strong>in</strong>stances” of local variablesI’m actually creat<strong>in</strong>g. A local variable is said to be <strong>in</strong>stantiated each time executionenters the scope where it’s declared. Here’s a simple example compar<strong>in</strong>g two verysimilar bits of code:<strong>in</strong>t s<strong>in</strong>gle;for (<strong>in</strong>t i=0; i < 10; i++){s<strong>in</strong>gle = 5;Console.WriteL<strong>in</strong>e(s<strong>in</strong>gle+i);}for (<strong>in</strong>t i=0; i < 10; i++){<strong>in</strong>t multiple = 5;Console.WriteL<strong>in</strong>e(multiple+i);}Licensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!