<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>GrantRi's WebLog [MS] : Anonymous Methods</title><link>http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx</link><description>Tags: Anonymous Methods</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Anonymous Method Usage</title><link>http://blogs.msdn.com/grantri/archive/2004/08/10/212268.aspx</link><pubDate>Tue, 10 Aug 2004 21:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:212268</guid><dc:creator>grantri</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/grantri/comments/212268.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=212268</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=212268</wfw:comment><description>&lt;P&gt;So now that Beta 1 has been out and fairly widely availible for a while, how do you use anonymous methods?&lt;/P&gt;
&lt;P&gt;When I was working on them I saw several contrived examples.&amp;nbsp; I saw several that seemed more like abuses than legitimate uses.&amp;nbsp; In my earlier posts I pointed out some of the problems the compiler has with 'optimizing' the code generated for anonymous methods and the methods that contain them.&amp;nbsp; In many cases I simply had to brainstorm with other until we came up with a logical guess for the most likely use and a solution that worked well for that case while not overly penalizing the less common cases.&lt;/P&gt;
&lt;P&gt;Are you a functional programmer that likes doing completions?&amp;nbsp; Do you try and morph C# into something more like Scheme or Lisp?&amp;nbsp; (I've seen code like this, but I've never felt comfortable writing code like this)&lt;/P&gt;
&lt;P&gt;Are you more of a Pascal hacker that uses anonymous methods like nested methods? (I've done this a few times)&lt;/P&gt;
&lt;P&gt;I haven't found a good name for this last style, so for now I'll call it the lazy style: where you use an anonymous method instead of&amp;nbsp; real method just because it's faster.&amp;nbsp; Like when a WinForms event handler only has one line of code, it just seems silly to write a whole method for that one line.&amp;nbsp; I have also seen this taken to extremes: a WinForm with all the event handlers inlined as anonymous methods into the form's InitializeComponents method!&amp;nbsp; In my mind this makes sense for small methods, but not big ones.&lt;/P&gt;
&lt;P&gt;Lastly, how you found problems with anonymous methods that prevent your from using them where you want to? For example: the performance is too slow, too much memory overhead, etc.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=212268" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item><item><title>More thoughts on Iterators</title><link>http://blogs.msdn.com/grantri/archive/2004/05/07/127714.aspx</link><pubDate>Fri, 07 May 2004 07:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:127714</guid><dc:creator>grantri</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/grantri/comments/127714.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=127714</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=127714</wfw:comment><description>&lt;P&gt;So I had a short email exchange with a collegue about iterators.&amp;nbsp; He mentioned that I should put in in my blog.&amp;nbsp; Seemed reasonable, so here it is:&lt;/P&gt;&lt;B&gt;
&lt;P dir=ltr&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P dir=ltr&gt;Subject:&lt;/B&gt; Iterator generated code&lt;/P&gt;
&lt;P&gt;...&lt;BR&gt;I'm looking at porting a hand-coded enumerator to use iterators (this is for a sample and maybe an article I have in mind to write about moving a production-quality collection to Whidbey)&lt;/P&gt;
&lt;P&gt;I'm decompiling the generated code with the latest .net reflector, as my IL isn't really up to much.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;My hand-written code tries hard to implement the full contract&amp;nbsp;from the&amp;nbsp;MSDN docs for IEnumerator, i.e. stuff like&amp;nbsp;throwing &lt;A href="ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/cpref/html/frlrfsysteminvalidoperationexceptionclasstopic.htm"&gt;InvalidOperationException&lt;/A&gt;&amp;nbsp;if the underlying collection changes in both Reset and MoveNext and throwing in Current if it is past the last element.&lt;/P&gt;
&lt;P&gt;I was wondering a couple of&amp;nbsp;things&amp;nbsp;&lt;/P&gt;
&lt;P&gt;a) Will the past last element&amp;nbsp;code get added to Current (i.e. state == -1)&lt;/P&gt;
&lt;P&gt;b) Will a Reset implementation be added?&lt;BR&gt;I can imagine that in many cases, the conditionals required to get to the yield return would be sufficient as a test in MoveNext and Reset, but I'm sure there are cases when it isn't.&lt;/P&gt;
&lt;P&gt;However I guess this would require&amp;nbsp;that any&amp;nbsp;initialiser code for user state would have to move into the constructor for this to work, as docs for Reset specify that it throws if the collection has changed between creation and Reset&lt;BR&gt;...&lt;/P&gt;
&lt;HR id=null align=center width="100%" SIZE=2&gt;
&lt;B&gt;Subject:&lt;/B&gt; RE: Iterator generated code 
&lt;P&gt;a) No.&amp;nbsp; The language designers specifically wanted the Current property to be inlineable, and NEVER to throw, even if it is accessed in an invalid state (before calling MoveNext, after MoveNext has returned false, when the collection has changed, etc.).&amp;nbsp; The general reason is that most people use foreach (or some equivalent) and there should be no reason to punish them performance-wise fo rhte few people who try to call Current some other way.&lt;/P&gt;
&lt;P&gt;b) Nope.&amp;nbsp; Again Anders mainly thought that enumerables are meant to be throw-away object and should never be reset.&amp;nbsp; He even pushed the generic form of IEnumerator to not have a Reset method (I think he would have removed it from the non-generic IEnumerator if it was possible).&lt;/P&gt;
&lt;P&gt;I've often wished we had some nice syntax to say "run this code xyz for each iteration".&amp;nbsp; The classic example is checking so see if the underlying collection has changed.&amp;nbsp; Without such syntax the user has to write boiler plate code (hopefully just calling a single method) before or after every yield.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;
&lt;HR tabIndex=-1 align=center width="100%" SIZE=2&gt;
&lt;B&gt;Subject:&lt;/B&gt; RE: Iterator generated code 
&lt;P&gt;...&lt;BR&gt;Would be good to position iterators as a performance-optimized foreach-server rather than a super-strict implementation of the IEnumerable contract.&lt;BR&gt;...&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;HR tabIndex=-1 align=center width="100%" SIZE=2&gt;

&lt;P&gt;This got me thinking some more about iterators.&amp;nbsp; The frameworks often use an int as a version field to detect when a collection has changed.&amp;nbsp; This seems like a bit of overkill and isn't 100% correct because it does suffer from wrap-around (although that is almost entirely impossible short of malicious code).&amp;nbsp; So I was wondering how you could write 100% correct code and still use an iterator, and have it be clean and maintainable code.&lt;/P&gt;
&lt;P&gt;My first thought was that you shouldn't need to increment the version all the time, only when there are live enumerator objects.&amp;nbsp; My next thought was that to have maintainable code the version checking and throwing should be encapsulated into a single method.&amp;nbsp; In C/C++ I would have used a macro to wrap up the version checking with the yield statement, but in C# I'm forced to just remeber to call my checker every place I yield.&lt;/P&gt;
&lt;P&gt;Well, for the method that checks the version and throws, I have 2 choices: on the outer collection class, or as an anonymous method inside the iterator.&amp;nbsp; Somehow the anonymous methods seems cleaner (and cooler) because it fits with the notion that an iterator effectively creates an anonymous class.&lt;/P&gt;
&lt;P&gt;Now back to detecting changes.&amp;nbsp; Instead of having an int, why not have an event that fires when the collection changes.&amp;nbsp; The iterator could subscribe to it with an anonymous method as well.&amp;nbsp; Then when there are no active iterators, there is little overhead (which is faster: a null check or an interlocked increment?).&lt;/P&gt;
&lt;P&gt;So here's some quick slapped together pseudo-code:&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;&lt;CODE&gt;public class SomeCollection {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private event EventHandler CollectionChanged;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void OnCollectionChanged() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler h = CollectionChanged;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (h != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; h(this, EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate void SimpleDelegate();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;SomeType&amp;gt; MyIterator() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool changed = false;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler changedHandler = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SimpleDelegate preCondition = delegate {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (changed)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new InvalidOperationException(...);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Possibly some other validation code here???&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; changedHandler = delegate {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; changed = true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Once it's changed, we don't need to know about future changes&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CollectionChanged -= changedHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; changed Handler = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CollectionChanged += changedHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return someValue;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; preCondition();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return someValue;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; preCondition();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (changedHandler != null) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CollectionChanged -= changedHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; changedHandler = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/CODE&gt;&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;So what do you think?&amp;nbsp; It's still not perfect because the event isn't subscribed to until the first call into MoveNext, which may happen significantly after the call to GetEnumerator.&amp;nbsp; The only way around that would be to wrap the iterator itself with another method that created the changedHandler, subscribed it and then passed in the changedHandler/preCondition pair to the real iterator method.&amp;nbsp; The down-side to that would be that if somebody called GetEnumerator twice on the same IEnumerable, both IEnumerators would share the same changedHandler/preCondition.&lt;/P&gt;
&lt;P&gt;It still does seem like an awful lot of boiler-plate code.&amp;nbsp; I might keep the notion of using an anonymous method as a way to pre and post conditions in an iterator, but using the int as a version for collections does seem to have fewer draw-backs (and a lot less boiler-plate code)...&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=127714" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Iterators/default.aspx">Iterators</category></item><item><title>Remoting...</title><link>http://blogs.msdn.com/grantri/archive/2004/04/17/115407.aspx</link><pubDate>Sun, 18 Apr 2004 05:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:115407</guid><dc:creator>grantri</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/grantri/comments/115407.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=115407</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=115407</wfw:comment><description>&lt;P&gt;First off, I don't even pretend to have a good comprehension of how remoting works.&lt;/P&gt;
&lt;P&gt;What I do know is that right now the compiler generated classes derive directly from Object, and somehow this is bad for remoting, instead they should derive from MarshalByReferenceObject.&amp;nbsp; On the surface that is a very simple change, but it has some possibly serious performance implications.&lt;/P&gt;
&lt;P&gt;Memory-wise, MBRO adds only a little bit.&amp;nbsp; Certainly not enough to outweight the benefits of better remoting.&amp;nbsp; The penalty comes when accessing fields of MBRO objects.&amp;nbsp; The penalty is that every field access gets indirected through a method call.&amp;nbsp; The method call is not needed when accessing fields off of the this pointer.&lt;/P&gt;
&lt;P&gt;With iterators, this is a non-issue because the fields are only accessed internally off of the this pointer.&amp;nbsp; Anonymous methods have the potential to be greatly impacted.&amp;nbsp; It's bad enough that a local is now heap based, but making a local access into a method call would just supprise too many people.&lt;/P&gt;
&lt;P&gt;So is there a way to have the best of both worlds: fast access and easy remoting?&amp;nbsp; Here are the two&amp;nbsp;ideas I've heard tossed around (well I guess one is mine):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Some keyword or syntax to specify whether a given anonymous method should be MBRO.&amp;nbsp; Then you, the programmer, can clearly decide if remoting is more important than accessing locals quickly.&amp;nbsp; The problem here is what syntax?&lt;/LI&gt;
&lt;LI&gt;Base it on the containing object.&amp;nbsp; This seems like a way of allowing you to decide, but without any extra syntax.&amp;nbsp; The problem is that many classes derive from frameworks classes that have already made that decision (and probably for different reasons).&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So here's your chance! Voice your thoughts and opinions.&amp;nbsp; Do you have a better idea?&amp;nbsp; Do you think I'm making a big deal over nothing?&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=115407" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Iterators/default.aspx">Iterators</category></item><item><title>A good author writes better than a good developer</title><link>http://blogs.msdn.com/grantri/archive/2004/03/30/104048.aspx</link><pubDate>Tue, 30 Mar 2004 18:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:104048</guid><dc:creator>grantri</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/grantri/comments/104048.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=104048</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=104048</wfw:comment><description>&lt;P&gt;So here's a recent MSDN article that I actually had the chance of reviewing several months ago.&amp;nbsp; They've done a much better job at capturing the good new stuff in C# than I could ever do.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/vcsharp/default.aspx?pull=/msdnmag/issues/04/05/c20/default.aspx"&gt;http://msdn.microsoft.com/vcsharp/default.aspx?pull=/msdnmag/issues/04/05/c20/default.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I do still have a few personal corrections:&lt;/P&gt;
&lt;P&gt;I commented that the internal names that the compiler generates have changed and will probably change again, and so the article should probably just mention that the name is compiler generated and not give the actual name (those that care can run ILDASM and see for themselves), but they didn't listen.&amp;nbsp; At least they did mention that is might change.&amp;nbsp; For those of you who have the community drop you'll notice that the compiler generated names&amp;nbsp;have changed from&amp;nbsp;what's in the article.&lt;/P&gt;
&lt;P&gt;I also commented that using the binary tree wasn't exactly the best example of iterators because of it's miserable performance.&amp;nbsp; Yes it is clean and neat code, but if you have a binary tree with 5000 nodes and you foreach it a few times, you can watch your machine crawl as it is forced to spend more and more time in the GC rather than running your code.&amp;nbsp;&amp;nbsp;At least&amp;nbsp;they&amp;nbsp;mentioned this potential problem (see the last paragraph before the Partial Types section).&amp;nbsp; Too bad my brain wasn't thinking and I got the numbers wrong.&amp;nbsp; It should state, &amp;#8220;approximately &lt;I&gt;n&lt;/I&gt;&lt;STRIKE&gt;/2&lt;/STRIKE&gt; iterator instantiations, where &lt;I&gt;n&lt;/I&gt; is the number of nodes in the tree.&amp;#8221;&lt;/P&gt;
&lt;P&gt;Also note the small paragraph on #pragma warning that now gives you line-level control over individual warnings!&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=104048" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Error+Messages+and+Warnings/default.aspx">Error Messages and Warnings</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Iterators/default.aspx">Iterators</category></item><item><title>Some Cool New Features</title><link>http://blogs.msdn.com/grantri/archive/2004/03/26/97112.aspx</link><pubDate>Fri, 26 Mar 2004 22:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97112</guid><dc:creator>grantri</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/grantri/comments/97112.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=97112</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=97112</wfw:comment><description>&lt;P&gt;I've been looking over some of my last few posts and they could easily come across as if I thought iterators and anonymous methods were the worst language features every added, and will never serve a good purpose.&amp;nbsp; If anything I think the opposite (or else I wouldn't have spent so much time on them).&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;BOLD&gt;&lt;STRONG&gt;Second only to generics I think iterators and anonymous methods are the coolest features added to the C# compiler.&lt;/BOLD&gt;&lt;/STRONG&gt;&lt;/EM&gt;&lt;STRONG&gt; &lt;/STRONG&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;So then why have I been writing all this negative stuff?&amp;nbsp; Well mainly because these guys are so powerful it's easy to write bad code and then blame it on the feature.&amp;nbsp; My goal is to point out their weaknesses so that you as educated developers can write clean, neat, &lt;STRONG&gt;and&lt;/STRONG&gt; efficient code, and not get burned.&amp;nbsp; I believe in general these are both very powerful features, but like most powerful things they can be quite deadly if used improperly.&amp;nbsp; Somehow I just don't feel like the MSDN docs are going to capture some of these gotchas in their 1/2 page topic on anonymous method or iterator syntax.&amp;nbsp; Also I'm already starting to see bad habits and styles floating around and the features haven't even been officially released yet!&lt;/P&gt;
&lt;P&gt;Well, if you've been itching to try them, we finally have an answer for you: Community Drops!&amp;nbsp; If you attend VSLive! or have a MSDN Universal subscription, we're sending out or first community drop.&amp;nbsp; One word of caution: this first&amp;nbsp;release was definitely date driven, so there are known bugs, but it's a lot newer than the Alpha bits a few of you already have.&amp;nbsp; I would personally recommend installing it on a 'throw away machine' (i.e. a machine you don't mind re-installing the OS on just to clean things up), but go out and try it.&amp;nbsp; Hopefully the higher-ups will come up with a sane schedule for us releasing more frequent drops like this.&amp;nbsp; Enjoy!&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/vs2005/"&gt;http://msdn.microsoft.com/vs2005/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=97112" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Iterators/default.aspx">Iterators</category></item><item><title>Anonymous Method Identity Crisis</title><link>http://blogs.msdn.com/grantri/archive/2004/03/25/96494.aspx</link><pubDate>Fri, 26 Mar 2004 01:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96494</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/96494.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=96494</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=96494</wfw:comment><description>&lt;P&gt;Delegates, like strings, have done some work so that&amp;nbsp;== behaves as expected, rather than as it should.&amp;nbsp; A delegate can be thought of as a tuple of the instance (or lack-of-instance in the case of delegates to static methods) and the method it invokes.&amp;nbsp; As long as those two items are the same, then the delegates are considered equal, regardless of whether or not there are 2 distinct GC objects holding that information.&amp;nbsp; This neat little trick allows people to&amp;nbsp;subscribe to an event, and discard that delegate instance.&amp;nbsp; Then when they need to unsbsubscribe, they create a new delegate (to the same instance and method) and use that to unsubscribe.&lt;/P&gt;
&lt;P&gt;Well that neat little coding pattern can burn you if applied to anonymous methods.&lt;/P&gt;
&lt;P&gt;The easiest one to explain is the fact that the language spec does not require 2 anonymous methods with the same bodies to be implemented by the same method.&amp;nbsp; So if you have the same anonymous method block in two places the compiler might or might not make them into the same method (our compiler doesn't right now).&lt;/P&gt;
&lt;P&gt;The second problem is a little trickier to explain.&amp;nbsp; Basically you have to remember that you don't directly control the instance of the delegate that points to an anonymous method.&amp;nbsp; It could be static, it could be the same as the current method, or it could be something else entirely.&amp;nbsp; If you really read closely my other posts, you can probably figure out how to read the code and determine what the compiler will do.&amp;nbsp;&amp;nbsp;&amp;nbsp;First that is just plain error prone.&amp;nbsp; It only takes one innocent edit to add or remove access to a parameter, a local, a field, or just about anything else, to change which instance the compiler will generate.&amp;nbsp; Secondly it is not spelled out int eh language spec, and is thus free to change between versions and implementations.&lt;/P&gt;
&lt;P&gt;Now you might be tempted to, &amp;#8220;so what if I can't unsubscribe from some event.&amp;#8221;&amp;nbsp; Well the biggest problem is lifetime.&amp;nbsp; As long as the anonymous method is subscribed to that event, it &lt;EM&gt;could&lt;/EM&gt; be keeping your class alive longer than needed.&amp;nbsp; That might then force you to use something like the allocation profiler to try and figure out why your memory characteristics suck.&lt;/P&gt;
&lt;P&gt;So now that I've convinced everybody, here' the right way to do stuff.&amp;nbsp; If you ever need the delegate that points to a given anonymous method in more than one place (like to unsubscribe), keep your own copy.&amp;nbsp; Store the delegate in a local, a field, a static someplace &lt;STRONG&gt;before&lt;/STRONG&gt; passing it off to anything else.&amp;nbsp; Do not rely on delegate equivalence, use good old fashioned reference equality.&amp;nbsp; Enjoy!&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=96494" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item><item><title>Anonymous method (and Iterator) perf</title><link>http://blogs.msdn.com/grantri/archive/2004/03/19/93094.aspx</link><pubDate>Sat, 20 Mar 2004 05:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:93094</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/93094.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=93094</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=93094</wfw:comment><description>&lt;P&gt;probably a few of you hav asked how to make iterators and anonymous methods fast.&amp;nbsp; Well hopefully if you understand how the compiler translates them, it should be relatively easy to optimize them.&amp;nbsp; The first thing to remember is that for all practical purposes the&amp;nbsp;C# compiler does not have an optimizer.&amp;nbsp; Thus the code that you write is fairly directly translated into IL.&amp;nbsp; The best way to optimize the IL is to optimize your code.&amp;nbsp; In the case of iterators and anonymous methods, I've tried (and I think this was the language designers' intent as well) to make the transformations farily transparent, so that the programmer can easily write educated and efficient code while taking advantage of these great features.&amp;nbsp; So here's my rules for making effecient anonymous methods and iterators (in no particular order):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Think carefully about which locals you use (a.k.a. capture).&amp;nbsp; As soon as you touch a local in an anonyous method, that local becomes heap based and goes through an extra level of indirection (and prevent enregistering).&lt;/LI&gt;
&lt;LI&gt;Think carefully about where locals are declared.&amp;nbsp; In order to maintain proper scoping semantics the compiler creates a new heap object on entry of each scope that has captured locals.&amp;nbsp; If you can move all the captured locals into one scope you'll probably get better perf.&amp;nbsp; If possible move that scope 'inward' to avoid an&amp;nbsp;GC object creation on a hot path (assuming the anonymous method is not on the hot path).&amp;nbsp; If possible move that scope out of loops&amp;nbsp;to avoid GC object creations on each iteration of the loop.&lt;/LI&gt;
&lt;LI&gt;The captured locals do not have to be in the same scope as the anonymous method.&amp;nbsp; The delegate that holds the anonymous method will be cached at the scope of the innermost captured local.&amp;nbsp; Thus if the locals are outside of a loop, but the anonymous method is inside, that's OK.&lt;/LI&gt;
&lt;LI&gt;Add extra scopes as hints to the compiler about lifetimes.&amp;nbsp; For iterators, any scopes without a 'yield return' statement will be mostly left intact, including using real locals for everytihg in that scope instead of heap-based fields.&lt;/LI&gt;
&lt;LI&gt;For iterators, if a try/finally block contains a yield statement, the finally block must be cloned from the MoveNext method into the Dispose method (so the same code is in two places).&lt;/LI&gt;
&lt;LI&gt;For iterators, calling GetEnumerator twice is just as expensive as calling the original iterator method/property/indexer twice.&lt;/LI&gt;
&lt;LI&gt;Iterators are designed to help amortize the cost of enumerations, so if you only need the first few elements, you don't need to pay the price for enumerating everything.&amp;nbsp; Follow that pattern in your own iterators where possible.&lt;/LI&gt;
&lt;LI&gt;Don't enumerate something twice when once will do.&amp;nbsp; Most enumerations have another method to obtain the count of elements without iterating.&amp;nbsp; So use that instead of iterating once just to count the elements, and then again to extract the values.&lt;/LI&gt;
&lt;LI&gt;Anonymous methods make some algorithms clearer, and iterators tend to make more correct IEnumerable/IEnumerator implementations, but neither of them will never be as efficient as hand written code (or hand written assembler, but who has time for that anymore).&amp;nbsp; So write well documented, clear, clean code, and then use a profiler to see if you need a speed improvement.&amp;nbsp; And remember that a faster algorithm will probably trump any micro-optimizations in your code (like counting down instead of up to avoid that one extra opcode on th eloop test)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I'm sure I think of more later, but that's most of them for now.&amp;nbsp; Enjoy, and feel free to correct me.&amp;nbsp; I can't wait until you guys can get a newer build and see the stuff we've been working on for almost the last year.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=93094" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Iterators/default.aspx">Iterators</category></item><item><title>Anonymous Methods: Alternate Syntax</title><link>http://blogs.msdn.com/grantri/archive/2004/03/18/92146.aspx</link><pubDate>Thu, 18 Mar 2004 18:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:92146</guid><dc:creator>grantri</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/grantri/comments/92146.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=92146</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=92146</wfw:comment><description>&lt;P&gt;A few of you have suggested alternate syntaxes for anonymous methods or just complained about their syntax.&amp;nbsp; Believe it or not syntax is very heavily discuess by the language design team (of which I am only an occasioanlly invited guest).&amp;nbsp; Iterators almost got cut because they couldn't come up with a good syntax.&amp;nbsp; So far I haven't seen a single syntax that the designers didn't at least glance at.&amp;nbsp; They wanted anonymous methods to be light-weight, but still clear and mostly understandable.&amp;nbsp; I guess there weren't enough scheme or lisp people in the design group&amp;nbsp; because most of those syntaxes dead ended on picking the right open and close characters that would work.&amp;nbsp; Square brackets were out because of arrays; angle brackets we're already overloaded between shifting, comparisons, and generics; parenthesis we're too ambigous; that left curly brackets.&amp;nbsp; Once they decided on curlies, it looked too much like a method body to &lt;STRONG&gt;not&lt;/STRONG&gt; have the parameter list on the outside.&amp;nbsp; The last decision to be made was 'keyword or no keyword'.&amp;nbsp; Hate me if you like, but I was in the keyword camp.&amp;nbsp; I just think the keyword makes things cleaner (not to mention prevents some ambiguities in the grammar).&amp;nbsp; But then they had to choose a keyword.&amp;nbsp; 'delegate' is a good clear word and I think it helps newbies understand what's going on a little.&amp;nbsp; My only complaint is that it's so darn long!&amp;nbsp; I wish we could have found an equally expressive and unambigous keyword that was only 2 or 3 characters long... :(&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=92146" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item><item><title>Anonymous Method Part 2 answers</title><link>http://blogs.msdn.com/grantri/archive/2004/03/09/87002.aspx</link><pubDate>Wed, 10 Mar 2004 03:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87002</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/87002.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=87002</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=87002</wfw:comment><description>I think the winner is Jerry Pisk. His final comment I think does the best job of explaining, what I was trying to explain. Thanks Jerry. I also partially agree with Jerry's first comment, namely anonymous methods can be confusing and lead to poor readability...(&lt;a href="http://blogs.msdn.com/grantri/archive/2004/03/09/87002.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=87002" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item><item><title>Anonymous Methods, Part 2 of ?</title><link>http://blogs.msdn.com/grantri/archive/2004/03/08/86291.aspx</link><pubDate>Tue, 09 Mar 2004 02:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:86291</guid><dc:creator>grantri</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/grantri/comments/86291.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=86291</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=86291</wfw:comment><description>&lt;P&gt;A lot of people seem to have trouble grasping how anonymous methods affect the lifetimes of locals.&amp;nbsp; SO hopefuly I can clarify that a little.&amp;nbsp; Previous to anonymous methods, the lifetime and the visibility of a local were identical for all practical purposes.&amp;nbsp; Because of the visibility restrictions, there was no way to tell if a loop was sharing the same instance of a local or using a new instance of a local.&amp;nbsp; Example:&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;
&lt;CODE&gt;void SomeMethod()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int outer = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; 10; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/CODE&gt;&lt;CODE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int inner = i;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("outer = {0}", outer++);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("i = {0}", i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("inner = {0}", ++inner);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/CODE&gt;&lt;CODE&gt;}&lt;/CODE&gt; 
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Here we have 3 locals: &lt;CODE&gt;outer&lt;/CODE&gt;, &lt;CODE&gt;i&lt;/CODE&gt;, and &lt;CODE&gt;inner&lt;/CODE&gt;.&amp;nbsp; Conceptually there is one instance of &lt;CODE&gt;outer&lt;/CODE&gt;, and &lt;CODE&gt;i&lt;/CODE&gt; for each invocation of &lt;CODE&gt;SomeMethod&lt;/CODE&gt;. I think everybody would agree to that so far.&amp;nbsp; Now comes the tricky part: there is conceptually a unique instance of &lt;CODE&gt;inner&lt;/CODE&gt; for each iteration of the loop or each entry into the containing scope.&amp;nbsp; That means that in this example there are 10 different instances of &lt;CODE&gt;inner&lt;/CODE&gt;.&amp;nbsp; However, because none of the lifetimes overlap, there is no way to detect this, and the C# compiler uses the same slot for all instances.&amp;nbsp; The runtime might even use the same register for each instance.&amp;nbsp; As soon as you add anonymous methods to the mix, then lifetimes do have the ability to overlap, and suddenly your code can percieve the different instances.&amp;nbsp; As an example, we'll modify the above code to not write out the variables directly, but instead create 10 anonymous methods (one for each loop) that does the same thing.&amp;nbsp; We'll run each anonymous method twice: once inside the loop when it is created, and once after the loop has finished.&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;delegate void NoArgs();&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;void SomeMethod()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NoArgs []&amp;nbsp;methods = new NoArgs[10];&lt;/CODE&gt;&lt;CODE&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int outer = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; 10; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/CODE&gt;&lt;CODE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int inner = i;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methods[i] = delegate {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("outer = {0}", outer++);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("i = {0}", i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("inner = {0}", ++inner);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methods[i]();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/CODE&gt;&lt;CODE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int&amp;nbsp;j = 0;&amp;nbsp;j &amp;lt; methods.Length; j++)&lt;BR&gt;&lt;CODE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; methods[j]();&lt;BR&gt;&lt;/CODE&gt;}&lt;/CODE&gt; 
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now test yourself and see if you can predict the actual output.&amp;nbsp; Just remember that the number of instances hasn't changed, only their lifetimes. The first time we run the anonymous methods, we get the exact same output as before: &lt;CODE&gt;outer&lt;/CODE&gt; counts from 0 to 9, &lt;CODE&gt;i&lt;/CODE&gt; counts from 0 to 9, and &lt;CODE&gt;inner&lt;/CODE&gt; counts from 1 to 10.&amp;nbsp; Now the second time we run the anonymous methods things might be a little supprising. &lt;CODE&gt;outer&lt;/CODE&gt; continues counting from 10 to 19, &lt;CODE&gt;i&lt;/CODE&gt; is stuck 10, and &lt;CODE&gt;inner&lt;/CODE&gt; looks like it is counting from 2 to 11!&amp;nbsp; If you think you know why, post a comment, or email me.&amp;nbsp; If this is so simple that I should stop wasting my time and yours, let me know.&amp;nbsp; Otherwise, I explain the whys and hows in my next few posts.&lt;/P&gt;
&lt;P&gt;Here's the acutal output:&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;
&lt;CODE&gt;outer = 0&lt;BR&gt;i = 0&lt;BR&gt;inner = 1&lt;BR&gt;outer = 1&lt;BR&gt;i = 1&lt;BR&gt;inner = 2&lt;BR&gt;outer = 2&lt;BR&gt;i = 2&lt;BR&gt;inner = 3&lt;BR&gt;outer = 3&lt;BR&gt;i = 3&lt;BR&gt;inner = 4&lt;BR&gt;outer = 4&lt;BR&gt;i = 4&lt;BR&gt;inner = 5&lt;BR&gt;outer = 5&lt;BR&gt;i = 5&lt;BR&gt;inner = 6&lt;BR&gt;outer = 6&lt;BR&gt;i = 6&lt;BR&gt;inner = 7&lt;BR&gt;outer = 7&lt;BR&gt;i = 7&lt;BR&gt;inner = 8&lt;BR&gt;outer = 8&lt;BR&gt;i = 8&lt;BR&gt;inner = 9&lt;BR&gt;outer = 9&lt;BR&gt;i = 9&lt;BR&gt;inner = 10&lt;BR&gt;outer = 10&lt;BR&gt;i = 10&lt;BR&gt;inner = 2&lt;BR&gt;outer = 11&lt;BR&gt;i = 10&lt;BR&gt;inner = 3&lt;BR&gt;outer = 12&lt;BR&gt;i = 10&lt;BR&gt;inner = 4&lt;BR&gt;outer = 13&lt;BR&gt;i = 10&lt;BR&gt;inner = 5&lt;BR&gt;outer = 14&lt;BR&gt;i = 10&lt;BR&gt;inner = 6&lt;BR&gt;outer = 15&lt;BR&gt;i = 10&lt;BR&gt;inner = 7&lt;BR&gt;outer = 16&lt;BR&gt;i = 10&lt;BR&gt;inner = 8&lt;BR&gt;outer = 17&lt;BR&gt;i = 10&lt;BR&gt;inner = 9&lt;BR&gt;outer = 18&lt;BR&gt;i = 10&lt;BR&gt;inner = 10&lt;BR&gt;outer = 19&lt;BR&gt;i = 10&lt;BR&gt;inner = 11&lt;/CODE&gt; 
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=86291" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item><item><title>Anonymous Methods, Part 1 of ?</title><link>http://blogs.msdn.com/grantri/archive/2004/02/05/68526.aspx</link><pubDate>Fri, 06 Feb 2004 07:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68526</guid><dc:creator>grantri</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/grantri/comments/68526.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=68526</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=68526</wfw:comment><description>&lt;P&gt;Although I was involved in many of the language design meetings, I don't think I can claim much of the credit for the actual design of the feature in the language spec.&amp;nbsp; There were a few technical gotchas that I discovered and proposed solutions to, and I'll try to remember to point them out as appropriate.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;First of all, although anonymous methods can be compared to several other features in several languages I think&amp;nbsp;they are different enough to really be classified as their own beast (if somebody does know of another language that really does have something like anonymous methods please enlighten me).&amp;nbsp; Functional programmers will be sad when they learn that the captured locals are read/write.&amp;nbsp; Anonymous methods are different from regular delegates because of their ability to capture a locals.&amp;nbsp; They aren't exactly anonymous classes (although with careful knowledge of how the compiler works you could use them as such).&lt;/P&gt;
&lt;P&gt;So what are anonymous&amp;nbsp;methods?&amp;nbsp; It is a way of writing an unnamed nested method that, just like most languages that have nested methods, allows access to all of the outer method's locals and parameters, including the 'this' parameter.&amp;nbsp; Here's where we hit the first gotcha.&amp;nbsp; In order to allow access to the outer method's locals and parameters we have to move them off of the stack onto the heap so they can live beyond the method execution and still be verifiable (no pointer arithmetic or passing of stack frame pointers into nested methods).&amp;nbsp; Well for starters we can't move reference parameters onto the heap, hence the restriction that ref or out parameters cannot be captured (used inside anonymous methods).&amp;nbsp; If you do need to do something like that the suggested&amp;nbsp;pattern to make&amp;nbsp;the code explicitly perform copy-in and/or copy-out semantics by assigning to or from a local of the same type.&lt;/P&gt;
&lt;P&gt;Example:
&lt;HR id=null&gt;
&lt;CODE&gt;void SomeMethod(ref int ri)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate {&amp;nbsp; ri++; } // This use is illegal because some users might expect&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the reference to outlive the method, and thus whenever they invoke the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // delegate some integer someplace gets incremented&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int copy_of_i = ri;&lt;BR&gt;&lt;/CODE&gt;&lt;CODE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;BR&gt;&amp;nbsp; &amp;nbsp; delegate { copy_of_i++; } // This is legal because now the programmer is&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // forced to realized the delegate can't mess with ri&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Then if the delegate is invoked, or copy-out is required&lt;/CODE&gt;&lt;CODE&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ri = copy_of_i;&lt;BR&gt;}&lt;/CODE&gt;
&lt;HR id=null&gt;
&lt;/P&gt;
&lt;P&gt;Now to complicate things even further, we have to remember that the 'this' pointer of structs is passed as if it was a reference parameter, that is why anonymous methods inside structs cannot access any instance members, while their counterparts inside classes can.&amp;nbsp; Again the suggested pattern to do a copy-in or copy-out as needed.&amp;nbsp; The language designers briefly toyed with the compiler automatically injecting the copy semantics, but them what happens when the real struct is modified on another thread?&amp;nbsp; Suddenly the user is able to perceive the difference between passing-by-reference and copy-in/copy-out.&amp;nbsp; Then there was also the question of where should the copy occur, and what happens when the delegate/method is invoked long after the outer method has returned, then there is no place to do the copy-out!&amp;nbsp; In the end we figured this was the safest route because it made it crystal clear what the compiler was going to do and the programmer would be forced into thinking about when and if a copy-out was needed.&amp;nbsp; I think that was probably my biggest contributions to anonymous methods.&lt;/P&gt;
&lt;P&gt;Now earlier I mentioned that the compiler moves all the locals from the stack onto the heap.&amp;nbsp; As you might have already guessed this involves allocation of a GC object.&amp;nbsp; The compiler works very hard to preserve the semantics of your original method, and as such tries to only create things when needed, but still in a very predictable manner.&amp;nbsp; To find out where an object will be created, simply look at the scopes.&amp;nbsp; Start at the outermost scope of the method (the open curly), and then work inward with this simple rule: if this scope contains any captured locals, the compiler will remove the local from the generated method and replace all the captured locals in that scope with fields in a new class.&amp;nbsp; The new class instance will be created on each entry into that scope (so that loops like for, foreach, do, while, will get new locals for&amp;nbsp;each iteration, but gotos within a scope will not).&amp;nbsp; So if you have 5 scopes each with one or more captured locals, you'll get 5 display classes.&amp;nbsp; So choose carefully which locals you capture and where they are declared.&amp;nbsp; In the outer method accessing a captured local becomes a single indirection through a display class.&amp;nbsp; From inside the anonymous method the local is often accessed as a member of 'this'.&amp;nbsp; The other performance gain that the compiler strives for is to eliminate extra delegate creations.&amp;nbsp; To accomplish that the compiler creates another local to cache the created delegate, thus if your anonymous method appears in the middle of a tight hot loop, as long as you don't capture any locals inside the loop, the constructed delegate will be cached outside the loop, and thus will only be created once and then successive loop iterations will only re-use the created delegate.&lt;/P&gt;
&lt;P&gt;So I guess my final point for this post will be be careful when writing new code.&amp;nbsp; Anonymous methods can be very very useful, and make certain programming tasks very easy, but &amp;#8220;with great power comes great responsibility&amp;#8220; because these wonderful anonymous methods, if used improperly can literally kill performance...&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=68526" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category></item></channel></rss>