Anonymous methods

T

Tony

Hello!

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

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

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();
}

//Tony
 
J

Jon Skeet [C# MVP]

Tony said:
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...
 
J

J.B. Moreno

Tony said:
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."

Usually scope lines up with the visual appearance of the code

class c
method m
block f (for for or if)

and when you leave or go "out of" a scope, a variable no longer exists.
Anonymous methods lead to an invisible expansion and thus
*continuation* of the scope of a variable.

If you create an anonymous method that refers to variable that LOOKS
like it is not local to the anonymous method, then that appearance is
incorrect -- the scope of the variable is the anonymous method.

This has implications for the value that is used in the anonymous
method, as well as for the system (i.e. when an object gets garbage
collected).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top