Frankie said:
Thank you Peter... RE:
<<they do really make it a LOT easier to deal with situations where you
want to use local variables (including method parameters) in the code. >>
Would an example of this [what you are talking about] be a situation
where an anonymous method is used in conjunction with the returning of a
delegate that makes use of an anonymous method, like this?:
...
return delegate() {... anonymous method here...}
or this?
....
someDelegateInstance += delegate {... anonymous method here...}
Since you didn't post any of the code inside the anonymous method, I can't
say whether those are an example of what I mean or not. In particular, if
the anonymous method doesn't reference any local variables, then
no...those aren't really examples of what I'm talking about.
If, on the other hand, they do reference local variables then sure...those
could be examples of what I'm talking about, even though they aren't
specifically what I had in mind.
If those do not qualify as examples of what you are talking about, can
you provide a brief example? Thanks!
Maybe Brian's reply has already elaborated this for you. But his
List.Find() example is exactly the sort of situation I had in mind. In
particular, .NET includes a lot of methods that take a predicate delegate,
used as a filter for some iterative process.
Often, you want the method implementing that predicate to be able to make
variable comparisons. That is, in some cases you can hard-code a
constant, but many situations call for passing in a value to use for a
comparison. In those cases, you need a place to put the value where the
method used for the predicate can get at it.
Without anonymous methods, the usual solution is to create a simple class
containing that value and the method. Then you instantiate the class,
initializing the value to the value you want, and creating the predicate
delegate using the method from the class:
class MyPredicateClass
{
int _i;
public MyPredicateClass(int i)
{
_i = i;
}
public bool MyPredicateMethod(int i)
{
return _i == i;
}
}
Then you use it in some method like this:
int MyIndexOf(List<int> list, int i)
{
MyPredicateClass mpc = new MyPredicateClass(i);
return list.FindIndex(mpc.MyPredicateMethod);
}
(Of course, the above is extremely simplistic, and already fully supported
by List<> without using predicates...in a real situation, the predicate
method would usually be doing a more complex evaluation. But for the
purposes of illustration, I think the simpler code is better).
Note the simple MyPredicateClass, the only purpose for which is to store
some data used by the predicate method. Using an anonymous method you
could do this much more simply as follows:
int MyIndexOf(List<int> list, int iFind)
{
return list.FindIndex(
delegate(int iObj) { return iObj == iFind; } );
}
The magic here is that the "iFind" local variable is "captured" by the
anonymous method, allowing it to be used by that method when it's used as
a predicate, without having to explicitly store it somewhere.
This sort of advantage is not by any means limited to anonymous methods
used as predicates. It just happens that the predicate scenario is a
fairly common and easily-explain example.
In the simplest cases, this is all you really need to know. You can start
using anonymous methods, making lots of good use of them, with just the
above information. Watch out though...anonymous methods do carry the
potential for some strange complications.

Read on...
Even if the anonymous method is used asynchronously, variables are still
captured and can live on past the lifetime of the scope where the
anonymous method was declared. For many situations this isn't an issue;
even if the anonymous method is used asynchronously (for example, as the
argument for a call to Control.BeginInvoke(), a reasonably common
asynchronous technique), often the variable being passed is a just a
value.
But if it's a reference type, and the object is mutable, then some other
code could change the object after the asynchronous call was made, but
before the anonymous method is actually executed, or the anonymous method
could asynchronously affect other code using the same object (if it
modifies the object). Similarly, local variables that are arguments
passed by reference ("out" or "ref") still act in the same way that they
would in the method to which they were passed, introducing some
potentially difficult synchronization issues.
So, with the added power of anonymous methods comes great responsibility
to use them wisely. But isn't that always the case?
Pete