Tony <jo*****************@telia.comwrote:
Here I have some text from a book I read. It says:
"An interesting point to note concerning anonymous methods is that they are
effectively local to the code
block that contains them, and they have access to local variables in this
scope. If you use such a variable
it becomes an outer variable. Outer variables are not disposed of when they
go out of scope like other
local variables are; instead, they live on until the anonymous method that
use them are destroyed.
This may be some time later than you expect and is definately something to
bed careful about."
The author is being *slightly* sloppy about terminology there, I
believe. In fact, any variable whose scope contains an inner method is
an outer variable. If the variable is *used* within an anonymous method
it becomes a *captured* outer variable (aka captured variable). It's
only captured outer variables whose lifetimes are extended.
I have one questions about the above text.
What does this mean in the text: "If you use such a variable
it becomes an outer variable. Outer variables are not disposed of when they
go out of scope like other
local variables are; instead, they live on until the anonymous method that
use them are destroyed.
This may be some time later than you expect and is definately something to
bed careful about."
Basically, it means the variable is no longer held on the stack.
Instead, it's held in an instance of a class - the anonymous method
holds a reference to an instance of the class, and the stack in the
method holds a reference to an instance too. Things become more
confusing when there are multiple "instances" of the variable due to
loops and things...
In main below I have defined an anonymous method. Is it possible that you
can exemplify the
answer by using main below and the anonymous method.
static void Main(string[] args)
{
Connection myConnection1 = new Connection();
myConnection1.Name = "First connection.";
myConnection1.MessageArrived += delegate(object source, EventArgs e)
{
Console.WriteLine("Message arrived from: {0}",
((Connection)source).Name);
Console.WriteLine("Message Text: {0}",
((MessageArrivedEventArgs)e).Message);
};
myConnection1.Connect();
Console.ReadKey();
}
There are no captured variables there - your anonymous method doesn't
use any of the local variables from the Main method. Here's an example
which does:
static void Main()
{
string text = "Hello!";
ThreadStart starter = delegate { Console.WriteLine(text); }
text = "Surprise!";
new Thread(starter).Start();
}
The "text" variable is captured by the anonymous method. Note that it's
the *variable* which is captured rather than just its initial value,
which is why the "Surprise!" is printed to the console. To learn what's
going on behind the scenes, I suggest you compile the code above and
then look at it carefully in reflector, flicking between the C# and IL
decompilations, and noting the extra class created for you.
Anonymous methods (and lambda expressions) are incredibly useful, but
mechanics are pretty complicated...
--
Jon Skeet - <sk***@pobox.com>
Web site:
http://www.pobox.com/~skeet
Blog:
http://www.msmvps.com/jon_skeet
C# in Depth:
http://csharpindepth.com