<?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>Fabulous Adventures In Coding : Immutability</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx</link><description>Tags: Immutability</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>What is this thing you call "thread safe"?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-thread-safe.aspx</link><pubDate>Mon, 19 Oct 2009 13:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9906219</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>29</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9906219.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9906219</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;STRONG&gt;Caveat: I am not an expert on multi-threading programming.&lt;/STRONG&gt; In fact, I wouldn't even say that I am &lt;EM&gt;competent&lt;/EM&gt; at it. My whole career, I've needed to write code to spin up a secondary worker thread probably less than half a dozen times. So take everything I say on the subject with some skepticism.&lt;/P&gt;
&lt;P&gt;A question I'm frequently asked: "&lt;EM&gt;is this code &lt;STRONG&gt;thread safe&lt;/STRONG&gt;?&lt;/EM&gt;" To answer the question, clearly we need to know what "thread safe" means.&lt;/P&gt;
&lt;P&gt;But before we get into that, there's something I want to clear up first. A question I am less frequently asked is "&lt;EM&gt;Eric, why does Michelle Pfeiffer always look so good in photographs?&lt;/EM&gt;"&amp;nbsp;To help answer this pressing question, I&amp;nbsp;consulted &lt;A class="" href="http://en.wikipedia.org/wiki/Photogenic" mce_href="http://en.wikipedia.org/wiki/Photogenic"&gt;Wikipedia&lt;/A&gt;:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;"A&amp;nbsp;&lt;B&gt;photogenic&lt;/B&gt; subject&amp;nbsp;is a subject that usually appears physically attractive or striking in photographs."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Why&amp;nbsp;does Michelle Pfeiffer always look so good in photographs? &lt;STRONG&gt;&lt;EM&gt;Because she's photogenic&lt;/EM&gt;.&lt;/STRONG&gt; Obviously.&lt;/P&gt;
&lt;P&gt;Well, I'm glad we've cleared up that mystery, but I seem to have wandered somehwat from the subject at hand. Wikipedia is &lt;A class="" href="http://en.wikipedia.org/wiki/Thread_safety" mce_href="http://en.wikipedia.org/wiki/Thread_safety"&gt;just as helpful in defining thread safety&lt;/A&gt;:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;&amp;nbsp;"A piece of code is &lt;B&gt;thread-safe&lt;/B&gt; if it functions correctly during simultaneous execution by multiple threads."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As with photogenicity, this&amp;nbsp;is obvious question-begging. When we ask "is this code &lt;EM&gt;thread safe&lt;/EM&gt;?" all we are really asking is "is this code &lt;EM&gt;correct&lt;/EM&gt; &lt;EM&gt;when called in a particular manner&lt;/EM&gt;?"&amp;nbsp;So how do we determine if the code is correct? &lt;STRONG&gt;We haven't actually explained anything here.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Wikipedia goes on:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;"In particular, it must satisfy the need for multiple threads to access the same shared data, ..."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;This seems fair; this scenario is almost always what people mean when they talk about thread safety. But then:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;"...and the need for a shared piece of data to be accessed by only one thread at any given time."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;Now we're talking about techniques for &lt;EM&gt;creating&lt;/EM&gt; thread safety, not &lt;EM&gt;defining&lt;/EM&gt; what thread safety means. Locking data so that it can only be accessed by one thread at a time is just one possible&amp;nbsp;technique for creating thread safety; it is not itself the definition of thread safety.&lt;/P&gt;
&lt;P mce_keep="true"&gt;My point is not that the definition is &lt;EM&gt;wrong&lt;/EM&gt;; as informal definitions of thread safety&amp;nbsp;go, this one is not terrible.&amp;nbsp;Rather, my point is&amp;nbsp;that the&amp;nbsp;definition indicates that the concept itself is &lt;EM&gt;completely vague&lt;/EM&gt; and essentially means nothing more than "behaves correctly in some situations". Therefore, when I'm asked "is this code thread safe?" I always have to push back and ask "what are the &lt;EM&gt;exact&lt;/EM&gt; &lt;EM&gt;threading scenarios&lt;/EM&gt; you are concerned about?" and "exactly what is &lt;EM&gt;correct behaviour&lt;/EM&gt; of the object in every one of those scenarios?"&lt;/P&gt;
&lt;P mce_keep="true"&gt;Communication problems arise when&amp;nbsp;people with different answers to those questions try to communicate about thread safety. For example, suppose I told you that I have a "threadsafe mutable queue" that you can use in your program.&amp;nbsp;You then cheerfully write the following code that runs on one thread while another thread is busy adding and removing items from the mutable queue:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;if (!queue.IsEmpty) Console.WriteLine(queue.Peek());&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Your code then crashes when the Peek throws a QueueEmptyException. What is going on here? I&amp;nbsp;said this&amp;nbsp;thing was thread safe, and yet your code is crashing in a multi-threaded scenario.&lt;/P&gt;
&lt;P mce_keep="true"&gt;When I said "the queue is threadsafe" I meant that the queue maintains its internal state consistently no matter what sequence of &lt;EM&gt;individual&lt;/EM&gt; operations are happening on other threads. But I did not mean that you can use my queue in any scenario that requires &lt;EM&gt;logical consistency maintained across multiple operations in a sequence&lt;/EM&gt;. In short, my opinion of "correct behaviour" and your opinion of the same differed because what we thought of as the relevant scenario was completely different. I care only about not crashing, but you care about being able to reason logically about the information returned from each method call.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In this example, you and I are probably&amp;nbsp;talking about different kinds of thread safety. Thread safety of mutable data structures is usually all about ensuring that the operations on the shared data always operate on the &lt;STRONG&gt;most up-to-date&lt;/STRONG&gt; state of the shared data as it mutates, even if that means that a particular combination of operations appears to be &lt;STRONG&gt;logically inconsistent&lt;/STRONG&gt;, as in our example above. Thread safety of immutable data structures is all about ensuring that use of&amp;nbsp;the data across all operations is &lt;STRONG&gt;logically consistent&lt;/STRONG&gt;, at the expense of the fact that you're looking at an&amp;nbsp;immutable&amp;nbsp;snapshot that might be &lt;STRONG&gt;out-of-date&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The problem here is that the choice about whether to access the first element or not is based on "stale" data. Designing a truly thread-safe mutable data structure in a world where &lt;EM&gt;nothing is allowed to be stale&lt;/EM&gt; can be&amp;nbsp;very difficult. Consider what you'd have to do in order to make the "Peek" operation above actually threadsafe. You'd need a new method:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;if (!queue.Peek(out first)) Console.WriteLine(first);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Is this "thread safe"? It certainly seems better.&amp;nbsp;But what if after the Peek, a different thread dequeues the queue? Now you're not crashing, but you've changed the behaviour of the previous program considerably. In the previous program, if, after the test there was a dequeue on another thread that changed what the first element was, then you'd either crash or&amp;nbsp;print out the up-to-date first element in the queue. Now you're printing out a &lt;EM&gt;stale&lt;/EM&gt; first element. Is that &lt;EM&gt;correct&lt;/EM&gt;? Not if we &lt;EM&gt;always&lt;/EM&gt; want to operate on up-to-date data!&lt;/P&gt;
&lt;P mce_keep="true"&gt;But wait a moment -- actually, the &lt;EM&gt;previous&lt;/EM&gt; version of the code had this problem as well. What if the dequeue on the other thread happened &lt;EM&gt;after&lt;/EM&gt; the call to Peek succeeded but &lt;EM&gt;before&lt;/EM&gt; the Console.WriteLine call executed? Again, you could be printing out stale data.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What if you want to ensure that you are always printing out up-to-date data? What you really need to make this threadsafe is:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;queue.DoSomethingToHead(first=&amp;gt;{Console.WriteLine(first);});&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Now the queue&amp;nbsp;author and the queue user agree on what the relevant scenarios are, so this is truly threadsafe. Right?&lt;/P&gt;
&lt;P mce_keep="true"&gt;Except... there could be something super-complicated in that delegate. What if whatever is in the delegate happens to cause an event that triggers code to run on another thread, which in turn causes some queue operation to run, which in turn blocks in such a manner that we've produced a deadlock? Is a deadlock "correct behaviour"? And if not, is&amp;nbsp;this method truly "safe"?&lt;/P&gt;
&lt;P mce_keep="true"&gt;Yuck.&lt;/P&gt;
&lt;P mce_keep="true"&gt;By now you take my point I'm sure.&amp;nbsp;As I pointed out earlier, &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2008/08/19/tasty-beverages.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2008/08/19/tasty-beverages.aspx"&gt;it is unhelpful to say that a building or a hunk of code is "secure" without somehow communicating &lt;STRONG&gt;which&amp;nbsp;threats&lt;/STRONG&gt;&amp;nbsp;the utilized security mechanism are and are not&amp;nbsp;proof against.&lt;/A&gt; Similarly,&amp;nbsp;&lt;STRONG&gt;it is unhelpful to say that code is "thread safe" without somehow communicating what undesirable&amp;nbsp;behaviors the utilized thread safety mechanisms do and do not prevent.&lt;/STRONG&gt; "Thread safety" is nothing more nor less than a code contract, like any other code contract. You agree to talk to an object in a particular manner, and it agrees to give you correct results if you do so; working out exactly what that manner is, and what the correct responses are, is a potentially tough problem.&lt;/P&gt;
&lt;P mce_keep="true"&gt;************&lt;/P&gt;
&lt;P&gt;(*) Yes, I'm aware that if I think something on Wikipedia is wrong, I can change it. There are two reasons why I should not do so.&amp;nbsp;First, as&amp;nbsp;I've already stated I'm not an expert in this area; I leave it to the experts to sort out amongst themselves what the right thing to say here is. And second, my point is not that the Wikipedia page is wrong, but rather that it illustrates that the term itself is&amp;nbsp;vague by nature.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9906219" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Wikipedia/default.aspx">Wikipedia</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Michelle+Pfeiffer/default.aspx">Michelle Pfeiffer</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Begging+the+question/default.aspx">Begging the question</category></item><item><title>Events and Races</title><link>http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx</link><pubDate>Wed, 29 Apr 2009 18:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9571319</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9571319.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9571319</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Here’s a question &lt;A class="" href="http://stackoverflow.com/questions/786383/c-events-and-thread-safety" mce_href="http://stackoverflow.com/questions/786383/c-events-and-thread-safety"&gt;similar&lt;/A&gt; to one I saw on &lt;A href="http://www.stackoverflow.com/" mce_href="http://www.stackoverflow.com"&gt;stackoverflow&lt;/A&gt; (*) the other day. Suppose you have an event:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public event Action Foo; &lt;/SPAN&gt;
&lt;P&gt;The standard pattern for firing this event is: &lt;SPAN class=code&gt;
&lt;P&gt;Action temp = Foo;&lt;BR&gt;if (temp != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temp();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What the heck is up with that? Why not just call “&lt;SPAN class=code&gt;Foo()&lt;/SPAN&gt;” ? &lt;/P&gt;
&lt;P&gt;First off, this pattern ensures that the thing that is invoked is not the null delegate reference, which would cause a null reference exception to be thrown. But if that’s what we want, then surely we could have skipped the temporary variable – just “&lt;SPAN class=code&gt;if (Foo != null) Foo();&lt;/SPAN&gt;” would do. Why the temp?&lt;/P&gt;
&lt;P&gt;The temporary variable ensures that this is “thread safe”. If the event’s handlers are being modified on another thread it is possible for Foo to be non-null at the point of the check, then set to null on a different thread, and then the invocation throws.&lt;/P&gt;
&lt;P&gt;Using the temporary variable effectively makes a copy of the current set of event handlers. Remember, &lt;STRONG&gt;multi-cast delegates are immutable&lt;/STRONG&gt;; when you add or remove a handler, you &lt;EM&gt;replace&lt;/EM&gt; the existing multi-cast delegate object with a &lt;EM&gt;different&lt;/EM&gt; delegate object that has different behaviour. You do not modify an existing &lt;EM&gt;object&lt;/EM&gt;, you modify the &lt;EM&gt;variable&lt;/EM&gt; that stores the event handler. Therefore, stashing away the current reference stored in that variable into a temporary variable effectively makes a copy of the current state.&lt;/P&gt;
&lt;P&gt;Is that clear? Make sure it is, because now things start to get really confusing.&lt;/P&gt;
&lt;P&gt;A common criticism of this pattern is that it trades one race condition for another. Let’s consider that scenario again more carefully:&lt;/P&gt;
&lt;P&gt;The event handler contains a single handler, H. Thread Alpha makes a copy of the delegate to H in temp and determines that it is not null. Thread Beta decides that H must no longer be called when the event is fired, so it sets the handler to null. Thread Beta then assumes that H will never be called, and destroys a bunch of state that H needs to execute successfully. Thread Alpha then regains control and executes H, which behaves crazily since its necessary state has been destroyed. Thread Beta’s attempt to ensure that H is not called has been defeated by the race condition.&lt;/P&gt;
&lt;P&gt;A frequently-stated principle of good software design is that code which calls attention to bugs by throwing exceptions is better than code which hides bugs by muddling on through and doing the wrong thing. This code has a race condition that results in incorrect behaviour. Perhaps an application of that principle is to stop using a temporary and instead crash if it races. That is to say, this code has a failure mode; surely it is better to highlight that failure with a crisp exception than to turn it into crazy wrong behaviour.&lt;/P&gt;
&lt;P&gt;That seems plausibly argued, I agree, but the conclusion is wrong. &lt;/P&gt;
&lt;P&gt;Suppose we remove the temporary variable but keep the null check. Does that &lt;EM&gt;solve&lt;/EM&gt; the problem? No! We still have the same race conditions. Suppose the event handler delegate contains a reference to H. Thread Alpha checks to see whether it is null; it is not. Thread Alpha pushes the object to invoke on the runtime stack. &lt;EM&gt;Between the push of the delegate value and the call to invoke it, thread Beta sets the event handler to null.&lt;/EM&gt; And once again, H will be invoked after thread Beta has removed the handler.&lt;/P&gt;
&lt;P&gt;Suppose we remove the temporary &lt;EM&gt;and&lt;/EM&gt; the null check and just invoke the delegate directly. Does that help? No, we &lt;EM&gt;still&lt;/EM&gt; have the same race condition. The contents of the event handling variable can still be changed between the push of the delegate object onto the stack and the invocation of the delegate.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Removing the code around the call site does not decrease the number of race conditions in the code, and it does increase the number of crashes. Worse, doing so makes the race condition harder to detect by shrinking the window in which the race can occur without eliminating it. &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Removing the null check and/or the temporary is a bad idea; the already-bad situation is only made worse.&lt;/P&gt;
&lt;P&gt;Essentially there are two problems here that are being conflated. The two problems are:&lt;/P&gt;
&lt;P&gt;1) The event handler delegate can be null at any time.&lt;BR&gt;2) A “stale” handler can be invoked even after it has been removed.&lt;/P&gt;
&lt;P&gt;These two problems are actually orthogonal and have different solutions. The onus for solving the first problem is laid upon the &lt;EM&gt;code which does the invocation&lt;/EM&gt;; it is required to ensure that it does not dereference null. The store-in-temporary-and-test pattern ensures that null is never dereferenced. (There are other ways to solve this problem; for example, initializing the handler to have an empty action that is never removed. But doing a null check is the standard pattern.)&lt;/P&gt;
&lt;P&gt;The onus for solving the second problem is laid upon &lt;EM&gt;the code being invoked&lt;/EM&gt;; &lt;STRONG&gt;event handlers are required to be robust in the face of being called even after the event has been unsubscribed.&lt;/STRONG&gt; In the scenario I described, &lt;STRONG&gt;the bug is actually in H&lt;/STRONG&gt;. It needs to be robust enough to check to see whether the state it needs is still there, and bail out cleanly if it is not. (Or, alternatively,&amp;nbsp;some additional locking mechanism needs to be implemented which ensures that the&amp;nbsp;code which fires the event cooperates with the code that changes the event handlers to ensure&amp;nbsp;the desired behaviour.)&lt;/P&gt;
&lt;P&gt;The point though is that the "null ref problem" and the "stale handler problem"&amp;nbsp;are two&amp;nbsp;separate problems that are easily confused because the symptoms of both arise at the exact same call site code. You've got to solve &lt;EM&gt;both&lt;/EM&gt; problems if you want to do threadsafe events. How you do so is up to you; just don't confuse the solution of one problem&amp;nbsp;for a solution of&amp;nbsp;the other.&lt;/P&gt;
&lt;P&gt;(Thanks to Microsofties Levi Broderick, Chris Burrows, Curt Hagenlocher and Wolf Logan; this article is based on a conversation about their analysis of this pattern.)&lt;/P&gt;
&lt;P&gt;*****************&lt;/P&gt;
&lt;P&gt;(*) A number of people have asked me why I do not post stuff like this to stackoverflow. &lt;/P&gt;
&lt;P&gt;First off, I want to say that stackoverflow is awesome, that incenting good behaviour through a reputation point system is genius, and that I applaud the collaborative problem solving culture exemplified by Jeff and Joel. Also, it is a valuable resource for me to see what people find confusing about the C# language.&lt;/P&gt;
&lt;P&gt;The thing is: everything that I write at work is the property of Microsoft Corporation. When I post Microsoft-owned content to my own blog on the MSDN site, I know that I can correct mistakes, there are no copyright issues, and any problems associated with, say, unfair use of the material are a problem for our lawyers. Also, my readers can be 100% clear that what I post here was written by me; there are no attribution issues.&lt;/P&gt;
&lt;P&gt;None of that is true when I post to third-party sites. I am not a lawyer; I do not know what the legal consequences are of posting Microsoft-owned material to a third party site, I don’t know that I’ll always be able to find and fix mistakes, and so on. &lt;/P&gt;
&lt;P&gt;I am sure that Jeff and Joel have a generous fair-use policy and mechanisms in place for posters to correct mistakes, I know they use a reasonable identity verification scheme, and so on. But notwithstanding all that, I’ve decided recently that it is my personal policy to not take on the burden of vetting third-party sites, even awesome ones. &lt;/P&gt;
&lt;P&gt;If the content I would have posted on stackoverflow is valuable then odds are good that it will reach the right people when I post it here.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9571319" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Quality/default.aspx">Code Quality</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Metablogging/default.aspx">Metablogging</category></item><item><title>Arrays considered somewhat harmful</title><link>http://blogs.msdn.com/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx</link><pubDate>Mon, 22 Sep 2008 21:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8961437</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>58</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8961437.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8961437</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I got a moral question from an author of programming language textbooks the other day requesting my opinions on whether or not beginner programmers should be taught how to use arrays.&lt;/P&gt;
&lt;P&gt;Rather than actually answer that question, I gave him a long&amp;nbsp;list of my opinions about&amp;nbsp;arrays, how I use arrays, how&amp;nbsp;we expect arrays to be used in the future, and so on. This gets a bit long, but like Pascal, I didn't have time to make it shorter.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Let me start by saying when you definitely should not use arrays, and then wax more philosophical about the future of modern programming and the role of the array in the coming world.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;You probably should not return an array as the value of a public method or property&lt;/STRONG&gt;, particularly when the information content of the array is logically immutable. Let me give you an example of where we got that horridly wrong in a very visible way in the framework.&amp;nbsp; If you take a look at the documentation for System.Type, you'll find that&amp;nbsp;just looking at the method descriptions gives one a sense of existential dread. One sees a whole lot of sentences like &lt;EM&gt;"Returns an array of Type objects that represent the constraints on the current generic type parameter." &lt;/EM&gt;Almost every method on System.Type returns an array it seems.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Now think about how that must be implemented. When you call, say, GetConstructors() on typeof(string), the implementation cannot possibly do this, as sensible as it seems.&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class Type { &lt;BR&gt;&amp;nbsp;&amp;nbsp; private ConstructorInfo[] ctorInfos;&lt;BR&gt;&amp;nbsp;&amp;nbsp; public ConstructorInfo[] GetConstructors()&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ctorInfos == null) ctorInfos = GoGetConstructorInfosFromMetadata();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ctorInfos;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Why? Because now the caller can take that array and &lt;EM&gt;replace the contents of it with whatever they please&lt;/EM&gt;. Returning an array means that &lt;STRONG&gt;you have to make a fresh copy of the array every time you return it&lt;/STRONG&gt;. You get called a hundred times, you’d better make a hundred array instances, no matter how large they are. It’s a performance nightmare – particularly if, like me, you are considering&amp;nbsp;using reflection to &lt;EM&gt;build a compiler&lt;/EM&gt;. Do you have any idea how many times a second I try to get type information out of reflection?&amp;nbsp; Not nearly as many times as I could; every time I do it’s another freakin’ array allocation!&lt;/P&gt;
&lt;P&gt;The frameworks designers were not foolish people; unfortunately, we did not have generic types in .NET 1.0. clearly the sensible thing now for GetConstructors() to return is IList&amp;lt;ConstructorInfo&amp;gt;. You can build yourself a nice read-only collection object once, and then just pass out references to it as much as you want. &lt;/P&gt;
&lt;P&gt;What is the root cause of this malaise? It is simple to state: The caller is requesting &lt;EM&gt;values&lt;/EM&gt;.&amp;nbsp; The callee fulfills the request by handing back &lt;EM&gt;variables&lt;/EM&gt;. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;An array is a collection of variables.&lt;/STRONG&gt; The caller doesn’t &lt;EM&gt;want&lt;/EM&gt; variables, but it’ll take them if that’s the only way to get the values. But in this case, as in most cases, &lt;EM&gt;neither the callee nor the caller wants those variables to ever vary&lt;/EM&gt;. Why on earth is the callee passing back variables then? &lt;STRONG&gt;Variables vary&lt;/STRONG&gt;. Therefore, a fresh, different variable must be passed back every time, so that if it does vary, nothing bad happens to anyone else who has requested the same values.&lt;/P&gt;
&lt;P&gt;If you are writing such an API, wrap the array in a ReadOnlyCollection&amp;lt;T&amp;gt; and return an IEnumerable&amp;lt;T&amp;gt; or an IList&amp;lt;T&amp;gt; or something, but not an array.&amp;nbsp; (And of course, do not simply cast the array to IEnumerable&amp;lt;T&amp;gt; and think you’re done!&amp;nbsp; That is still passing out variables; the caller can simply cast back to array!&amp;nbsp; Only pass out an array if it is wrapped up by a read-only object.)&lt;/P&gt;
&lt;P&gt;That’s the situation at present. What are the implications of array characteristics for the future of programming and programming languages?&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Parallelism Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;The physics aspects of Moore’s so-called “Law” are failing, as they eventually must. Clock speeds have stopped increasing, transistor density has stopped increasing. The laws of thermodynamics and the Uncertainty Principle are seeing to that. But manufacturing costs per chip are still falling, which means that our only hope of Moore’s "Law" continuing to hold over the coming decades is to cram more and more processors into each box.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We’re going to need programming languages that allow mere mortals to write code that is parallelizable to multiple cores.&lt;/P&gt;
&lt;P&gt;Side-effecting change is the enemy of parallelization. Parallelizing in a world with observable side effects means locks, and locks means choosing between implementing lock ordering and dealing with random crashes or deadlocks. Lock ordering requires global knowledge of the program. Programs are becoming increasingly complex, to the point where one person cannot reasonably and confidently have global knowledge. Indeed, we prefer programming languages to have the property that programs in them can be understood by understanding one part at a time, not having to swallow the whole thing in one gulp.&lt;/P&gt;
&lt;P&gt;Therefore we tools providers need to create ways for people to program effectively &lt;EM&gt;without causing observable side effects&lt;/EM&gt;. &lt;/P&gt;
&lt;P&gt;Of all the sort of “basic” types, &lt;STRONG&gt;arrays most strongly work against this goal&lt;/STRONG&gt;. An array’s whole purpose is to be a mass of mutable state. Mutable state is hard for both humans and compilers to reason about. It will be hard for us to write compilers in the future that generate performant multi-core programs if developers use a lot of arrays.&lt;/P&gt;
&lt;P&gt;Now, one might reasonably point out that List&amp;lt;T&amp;gt; is a mass of mutable state too. But at least one could create a threadsafe list class, or an immutable list class, or a list class that has transactional integrity, or&amp;nbsp;uses some form of isolation&amp;nbsp;or whatever. We have an extensibility model for lists because &lt;EM&gt;lists are classes&lt;/EM&gt;. We have no ability to make an “immutable array”. Arrays are what they are and they’re never going to change.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Conceptual Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;We want C# to be a language in which one can draw a line between code that implements a mechanism and code that implements a policy. &lt;/P&gt;
&lt;P&gt;The “C” programming language is all about mechanisms. It lays bare almost exactly what the processor is actually doing, providing only the thinnest abstraction over the memory model. And though we want you to be able to write programs like that in C#, most of the time people should be writing code in the “policy” realm. That is, code that emphasizes &lt;EM&gt;what the code is supposed to do, &lt;/EM&gt;not &lt;EM&gt;how it does it.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Coding which is more declarative than imperative, coding which avoids side effects, coding which emphasizes algorithms and purposes over mechanisms, that kind of coding is the future in a world of parallelism. (And you’ll note that LINQ is designed to be declarative, strongly abstract away from mechanisms, and be free of side effects.)&lt;/P&gt;
&lt;P&gt;Arrays work against all of these factors. Arrays demand imperative code, arrays are all about side effects, arrays make you write code which emphasizes how the code works, not what the code is doing or why it is doing it. Arrays make optimizing for things like “swapping two values” easy, but destroy the larger ability to optimize for parallelism.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Practical Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;And finally, given that arrays are mutable by design, the way an array restricts that mutability is deeply weird. All the &lt;EM&gt;contents&lt;/EM&gt; of the collection are mutable, but the &lt;EM&gt;size&lt;/EM&gt; is fixed.&amp;nbsp; What is up with that? Does that solve a problem anyone actually has?&lt;/P&gt;
&lt;P&gt;For this reason alone I do almost no programming with arrays anymore. Arrays simply do not model any problem that I have at all well – I rarely need a collection which has the rather contradictory properties of being &lt;EM&gt;completely mutable&lt;/EM&gt;, and at the same time, &lt;EM&gt;fixed in size&lt;/EM&gt;. If I want to mutate a collection it is almost always to add something to it or remove something from it, not to change what value an index maps to.&lt;/P&gt;
&lt;P&gt;We have a class or interface for everything I need. If I need a sequence I’ll use IEnumerable&amp;lt;T&amp;gt;, if I need a mapping from contiguous numbers to data I’ll use a List&amp;lt;T&amp;gt;, if I need a mapping across arbitrary data I’ll use a Dictionary&amp;lt;K,V&amp;gt;, if I need a set I’ll use a HashSet&amp;lt;T&amp;gt;. I simply don’t need arrays for anything, so I almost never use them. They don’t solve a problem I have better than the other tools at my disposal.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Pedagogic Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;It is&amp;nbsp;important that beginning programmers understand arrays; it is an important and widely used concept. But it is also important to me that they understand the weaknesses and shortcomings of arrays. In almost every case, there is a better tool to use than an array.&lt;/P&gt;
&lt;P&gt;The difficulty is, pedagogically, that it is hard to discuss the merits of those tools without already having down concepts like classes, interfaces, generics, asymptotic performance, query expressions, and so on. It’s a hard problem for the writer and for the teacher. Fortunately, for me, it's not a problem that I personally have to solve.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8961437" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rants/default.aspx">Rants</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Quality/default.aspx">Code Quality</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Software+development+methodology/default.aspx">Software development methodology</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Arrays/default.aspx">Arrays</category></item><item><title>Mutating Readonly Structs </title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx</link><pubDate>Wed, 14 May 2008 17:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8481327</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>27</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8481327.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8481327</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Consider this program which attempts to mutate a readonly mutable struct. What happens?&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;struct Mutable {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int x;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Mutate()&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.x = this.x + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.x;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;class Test {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public readonly Mutable m = new Mutable();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test t = new Test();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(t.m.Mutate());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(t.m.Mutate());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine(t.m.Mutate());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;There are a number of things this program could do. Does it:&lt;/P&gt;
&lt;P&gt;1)&amp;nbsp;Print 1, 2, 3 -- because m is readonly, but the "readonly" only applies to m, not to its contents. &lt;BR&gt;2) Print 0, 0, 0 -- because m is readonly, x cannot be changed. It always has its default value of zero.&lt;BR&gt;3) Throw an exception at runtime, when the attempt is made to mutate the contents of a readonly field.&lt;BR&gt;4) Do something else&lt;/P&gt;
&lt;P&gt;?&lt;/P&gt;
&lt;P&gt;People are frequently surprised to learn that the answer is (4). In fact, this prints 1, 1, 1.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Why?&lt;/P&gt;
&lt;P&gt;Because, remember, accessing a value type gives you a COPY of the value. When you say t.m, you get a copy of whatever is presently stored in m. m is immutable, but the copy is not. The copy is then mutated, and the value of x in the copy is returned.&amp;nbsp;But m remains untouched.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The relevant section of the specification is 7.5.4, which states that&amp;nbsp;when resolving "E.I" where E is an object and I is a field...&lt;/P&gt;&lt;SPAN class=spec&gt;
&lt;P&gt;...if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The important word here is that the result is the &lt;EM&gt;value&lt;/EM&gt; of the field,&amp;nbsp;not the &lt;EM&gt;variable&lt;/EM&gt; associated with the field. &lt;EM&gt;Readonly fields are not variables outside of the constructor&lt;/EM&gt;. (&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx" target=_blank mce_href="http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx"&gt;The initializer here&amp;nbsp;is considered to be inside the constructor; see my earlier post on that subject&lt;/A&gt;.)&lt;/P&gt;
&lt;P mce_keep="true"&gt;Great. What about that second dot, as in ".Mutate()"?&amp;nbsp; We look&amp;nbsp;at section 7.4.4 to find out how to invoke E.M():&lt;/P&gt;&lt;SPAN class=spec&gt;
&lt;P&gt;If E is not classified as a variable, then a temporary local variable&amp;nbsp;of E's type is created and the value of E is assigned to that variable. E is then reclassified as a reference to that temporary local variable. The temporary variable is accessible as &lt;EM&gt;this&lt;/EM&gt; within M, but not in any other way. Thus, only when E is a true variable is it possible for the&amp;nbsp;caller to observe the changes that M makes to &lt;EM&gt;this&lt;/EM&gt;.&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;And there you go. Value semantics are tricky!&lt;/P&gt;
&lt;P mce_keep="true"&gt;This is yet another reason why mutable value types are evil. Try to always make value types immutable.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8481327" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Puzzles/default.aspx">Puzzles</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Trivial Projections Are (Usually) Optimized Away</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/12/trivial-projections-are-usually-optimized-away.aspx</link><pubDate>Mon, 12 May 2008 16:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8481233</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8481233.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8481233</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;OK, computers aren't &lt;EM&gt;entirely&lt;/EM&gt; dumb when it comes to LINQ. Here's an example of a place where we're a bit smarter.&lt;/P&gt;
&lt;P&gt;Consider the following query:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IEnumerable&amp;lt;int&amp;gt; query = from n in number_array orderby n select n;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Does this get transformed by the compiler into&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IEnumerable&amp;lt;int&amp;gt; query = number_array.OrderBy(n =&amp;gt; n);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;or&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IEnumerable&amp;lt;int&amp;gt; query = number_array.OrderBy(n =&amp;gt; n).Select( n =&amp;gt; n );&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;?&lt;/P&gt;
&lt;P&gt;This question caused tremendous debate amongst the members of the C# design and implementation teams. I am quite happy with the compromise we achieved.&lt;/P&gt;
&lt;P&gt;The sections of the C# specification which cover this topic are sections 7.15.2.3, and 7.15.2.5:&lt;/P&gt;
&lt;P&gt;*** &lt;/P&gt;&lt;SPAN class=spec&gt;
&lt;P&gt;A query expression of the form “from x in e select v” is translated into “( e ) . Select ( x =&amp;gt; v )” except when v is the identifier x, the translation is simply “( e )”&lt;/P&gt;
&lt;P&gt;A query expression of the form “from x in e select x” is translated into “( e ) . Select ( x =&amp;gt; x )”.&lt;/P&gt;
&lt;P&gt;A degenerate query expression is one that trivially selects the elements of the source. A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. It is then up to the implementers of Select and other query operators to ensure that these methods never return the source object itself.&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;*** &lt;/P&gt;
&lt;P&gt;It might sound like the second statement contradicts the first. The first statement says that the “&lt;SPAN class=code&gt;.Select(x=&amp;gt;v)&lt;/SPAN&gt;” is omitted when “&lt;SPAN class=code&gt;v&lt;/SPAN&gt;” is “&lt;SPAN class=code&gt;x&lt;/SPAN&gt;”, and the second statement says that no, the “&lt;SPAN class=code&gt;.Select(x=&amp;gt;x)&lt;/SPAN&gt;” is in fact generated. &lt;/P&gt;
&lt;P&gt;The spec is not particularly clear on this point, I agree, though the explanatory text about “degenerate query expressions” does help clear it up somewhat. Basically what we are saying here is that the optimization to remove degenerate selects is only performed on the result of an earlier query translation. &lt;/P&gt;
&lt;P&gt;Some examples will help.&lt;/P&gt;
&lt;P&gt;If you have &lt;SPAN class=code&gt;from n in number_array orderby n select n&lt;/SPAN&gt; then this is first translated into &lt;SPAN class=code&gt;from n in (number_array).OrderBy(n=&amp;gt;n) select n &lt;/SPAN&gt;and then, since the selector is the same as the range variable, this is translated into &lt;SPAN class=code&gt;((number_array).OrderBy(n=&amp;gt;n))&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;We optimize away the &lt;SPAN class=code&gt;Select(n=&amp;gt;n)&lt;/SPAN&gt; because &lt;SPAN class=code&gt;from n in (number_array).OrderBy(n=&amp;gt;n) select n &lt;/SPAN&gt;is the intermediate result of an earlier query translation.&lt;/P&gt;
&lt;P&gt;If you had &lt;SPAN class=code&gt;from n in number_array select n &lt;/SPAN&gt;then this would be considered a degenerate query expression requiring a &lt;SPAN class=code&gt;Select&lt;/SPAN&gt;. We cannot simply translate it into &lt;SPAN class=code&gt;(number_array)&lt;/SPAN&gt; because then you could assign that to a variable and have referential identity with the collection. The result of the query should not “leak” information about the collection out; it should just be an enumerable object of the appropriate type, and not have an identity relationship. Therefore, we take the performance hit and protect the identity of the collection by emitting a degenerate query translation &lt;SPAN class=code&gt;(number_array).Select(n=&amp;gt;n)&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;This is important because the collection might be a mutable collection. One does not expect that the result of a &lt;EM&gt;query&lt;/EM&gt; over that collection could be used to mutate the collection! The query results should be read-only.&lt;/P&gt;
&lt;P&gt;We do not need to append the degenerate &lt;SPAN class=code&gt;Select(n=&amp;gt;n)&lt;/SPAN&gt; when you have an “&lt;SPAN class=code&gt;orderby”&lt;/SPAN&gt; in there because the &lt;SPAN class=code&gt;OrderBy(n=&amp;gt;n)&lt;/SPAN&gt; call already protects the identity of the original collection. This saves on the performance cost of the no-op &lt;SPAN class=code&gt;Select&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;I think we’ve made a reasonable compromise in the case of degenerate queries. If you are crazy enough to write “&lt;SPAN class=code&gt;from x in xs select x&lt;/SPAN&gt;” when you mean “&lt;SPAN class=code&gt;(xs)&lt;/SPAN&gt;”, then you’ll have to live with the decreased performance. But if you are introducing a degenerate select at the end of a meaningful query, then it will be optimized away.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8481233" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Protected Semantics, Part Five: More on immutability</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/05/protected-semantics-part-five-more-on-immutability.aspx</link><pubDate>Mon, 05 May 2008 19:52:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8460893</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8460893.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8460893</wfw:commentRss><description>&lt;div class="mine"&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;I asked a second follow-up question back in Part Two:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000a0"&gt;Suppose you wanted to make this hierarchy an immutable collection, where "Add" and "Remove" returned new collections rather than mutating the existing collection. How would you represent the parenting relationship?&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The short answer is "I wouldn't". First off, it sounds an awful lot like what is intended to be represented here is some sort of highly mutable system, where objects are being added and removed from containers. It might be more sensible to represent that thing using mutable data structures rather than immutable data structures.&lt;/p&gt; &lt;p&gt;If you did want to represent the thing with immutable data structures, then I would think twice before attempting to represent parenting at all. Here's why: when you have an immutable tree structure without parents, and you want to make a new tree structure that is based on an old one, typically the only stuff you have to change is from the edited node on up to the root node; usually hierarchies are shallow, so this is not very many nodes.&lt;/p&gt; &lt;p&gt;But this logically implies that the root node changes on every edit. If the root node changes, then all of its children have a new parent, and all of their children then have a new parent... and you've just rewritten the entire tree structure, not just a few nodes. &lt;/p&gt; &lt;p&gt;Now, it is often highly convenient to know what the parent of a given node is. To achieve that, what I'd probably do is try to not need to query the parent of any node until I was at a point where I wanted to ask about a lot of parents, and the tree was likely to remain unedited while I was asking. A quick visitor pass that builds up a hash table mapping every node to its parent would be easy enough to write, and then the parent table could be discarded and its memory reclaimed once I was done. &lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8460893" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Why Do Initializers Run In The Opposite Order As Constructors? Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx</link><pubDate>Mon, 18 Feb 2008 18:25:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7724412</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>42</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7724412.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7724412</wfw:commentRss><description>&lt;div class="mine"&gt; &lt;p&gt;As you might have figured out, the answer to last week's puzzle is "if the constructors and initializers run in their actual order then an initialized readonly field of reference type is guaranteed to be non null in any possible call. That guarantee cannot be met if the initializers run in the expected order." &lt;p&gt;Suppose counterfactually that initializers ran in the expected order, that is, derived class initializers run after the base class constructor body. Consider the following pathological cases:&lt;/p&gt;&lt;span class="code"&gt; &lt;p&gt;class Base&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static ThreadsafeCollection t = new ThreadsafeCollection();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Base()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Base constructor");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this is Derived) (this as Derived).DoIt(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // would deref null if we are constructing an instance of Derived&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Blah(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // would deref null if we are constructing an instance of MoreDerived&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t.Add(this);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // would deref null if another thread calls Base.t.GetLatest().Blah();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // before derived constructor runs&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual void Blah() { }&lt;br&gt;} &lt;br&gt;class Derived : Base&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; readonly Foo derivedFoo = new Foo("Derived initializer");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DoIt()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; derivedFoo.Bar();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;}&lt;br&gt;class MoreDerived : Derived&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void Blah() { DoIt(); }&lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;/span&gt;Calling methods on derived types from constructors is dirty pool, but it is not illegal. And stuffing not-quite-constructed objects into global state is risky, but not illegal. I'm not recommending that you do any of these things -- please, do not, for the good of us all. I'm saying that it would be really nice if we could give you an ironclad guarantee that an initialized readonly field is always observed in its initialized state, and we cannot make that guarantee unless we run all the initializers first, and then all of the constructor bodies.&lt;/p&gt; &lt;p&gt;Note that of course, if you initialize your readonly fields in the constructor, then all bets are off. We make no guarantees as to the fields not being accessed before the constructor bodies run. &lt;/p&gt; &lt;p&gt;Next time on FAIC: how to get a question &lt;em&gt;not&lt;/em&gt; answered.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7724412" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Puzzles/default.aspx">Puzzles</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Why Do Initializers Run In The Opposite Order As Constructors? Part One</title><link>http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx</link><pubDate>Sat, 16 Feb 2008 02:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7724010</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>34</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7724010.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7724010</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Pop quiz! 
&lt;P&gt;What do you expect the output of this program to be? 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;using System; 
&lt;P&gt;class Foo&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Foo(string s)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Foo constructor: {0}", s);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Bar() { }&lt;BR&gt;} &lt;BR&gt;class Base&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; readonly Foo baseFoo = new Foo("Base initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Base()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Base constructor");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;BR&gt;class Derived : Base&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; readonly Foo derivedFoo = new Foo("Derived initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Derived()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Derived constructor");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;BR&gt;static class Program&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Derived();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;I got a question from a user recently noting that the order was not as he expected. One naively expects that the order will go "base initializers, base constructor body, derived initializers, derived constructor body". In fact the order actually is that first all the initializers run in order &lt;EM&gt;from derived to base&lt;/EM&gt;, and then all the constructor bodies run in order &lt;EM&gt;from base to derived&lt;/EM&gt;. 
&lt;P&gt;The latter bit makes perfect sense; the more derived constructors may rely upon state initialized by the less derived constructors, so the constructors should run in order from base to derived. But most people assume that the call sequence of the code above is equivalent to this pseudocode: &lt;SPAN class=code&gt;
&lt;P&gt;// Expected&lt;BR&gt;BaseConstructor()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ObjectConstructor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; baseFoo = new Foo("Base initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Base constructor");&lt;BR&gt;} &lt;BR&gt;DerivedConstructor()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BaseConstructor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; derivedFoo = new Foo("Derived initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Derived constructor");&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;When in point of fact it is equivalent to this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;SPAN class=code&gt;// Actual&lt;BR&gt;BaseConstructor()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; baseFoo = new Foo("Base initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ObjectConstructor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Base constructor");&lt;BR&gt;} &lt;BR&gt;DerivedConstructor()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; derivedFoo = new Foo("Derived initializer");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BaseConstructor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Derived constructor");&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;That explains the &lt;EM&gt;mechanism&lt;/EM&gt; whereby the initializers run in order from derived to base and the constructor bodies run in the opposite order, but why did we choose to implement that mechanism instead of the more intuitively obvious former way? 
&lt;P&gt;Puzzle that one over for a bit, and then read on for a hint. 
&lt;P&gt;... 
&lt;P&gt;... 
&lt;P&gt;... 
&lt;P&gt;The "readonly" modifiers in there were no accident. The code gives the appearance that any call to &lt;SPAN class=code&gt;derivedFoo.Bar()&lt;/SPAN&gt; and &lt;SPAN class=code&gt;baseFoo.Bar()&lt;/SPAN&gt; should never fail with a null dereference exception because both are readonly fields initialized to non-null values. 
&lt;OL&gt;
&lt;LI&gt;Is that appearance accurate, or misleading?&lt;/LI&gt;
&lt;LI&gt;Now suppose initializers ran in the "expected" order and answer question (1) again.&amp;nbsp; &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;I'll post the answers and analysis next week. Have a fabulous weekend! 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7724010" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Puzzles/default.aspx">Puzzles</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Eleven: A working double-ended queue</title><link>http://blogs.msdn.com/ericlippert/archive/2008/02/12/immutability-in-c-part-eleven-a-working-double-ended-queue.aspx</link><pubDate>Wed, 13 Feb 2008 02:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7656893</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7656893.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7656893</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;At long last, let's get to that double-ended queue. Sorry for leaving you in suspense!&lt;/P&gt;
&lt;P&gt;Last time we came up with a non-solution -- as commenters immediately discovered, the given algorithm and data structure are deeply inefficient.&amp;nbsp; However, the basic &lt;EM&gt;idea&lt;/EM&gt; is sound. There are a number of ways to solve this problem, but the way I'm going to talk about today is a much more efficient variation on the theme of our previous unsuccessful attempt. That is, have &lt;STRONG&gt;cheap access to the endpoints&lt;/STRONG&gt;, and have some kind of more expensive "cold storage" in the middle. &lt;/P&gt;
&lt;P&gt;In order to solve this problem I'm first going to introduce some helper classes which solve a much simpler problem. I want to implement a very limited kind of deque, namely one which can only store one, two, three or four items. A "dequelette", if you'll allow the silly name. &lt;/P&gt;
&lt;P&gt;Note that there is no "empty" dequelette. Since this class does not actually fulfill the contract for a deque, I'm not going to have it implement &lt;SPAN class=code&gt;IDeque&amp;lt;T&amp;gt;&lt;/SPAN&gt;. Rather, I'll just have a base class that these four dequelette types derive from:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class Deque&amp;lt;T&amp;gt; : IDeque&amp;lt;T&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; private abstract class Dequelette&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract int Size { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual bool Full { get { return false; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract T PeekLeft();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract T PeekRight();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract Dequelette EnqueueLeft(T t);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract Dequelette EnqueueRight(T t);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract Dequelette DequeueLeft();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract Dequelette DequeueRight();&lt;BR&gt;&amp;nbsp; } &lt;/SPAN&gt;
&lt;P&gt;The implementations of dequelette classes &lt;SPAN class=code&gt;One&lt;/SPAN&gt;, &lt;SPAN class=code&gt;Two&lt;/SPAN&gt;, &lt;SPAN class=code&gt;Three&lt;/SPAN&gt; and &lt;SPAN class=code&gt;Four&lt;/SPAN&gt; are obvious; rather than take up a lot of space here, I'll put them on a &lt;A href="http://blogs.msdn.com/ericlippert/pages/deque-cs.aspx" mce_href="http://blogs.msdn.com/ericlippert/pages/deque-cs.aspx"&gt;separate page&lt;/A&gt; along with the rest of the implementation.&lt;/P&gt;
&lt;P&gt;OK. What does this trivial little class hierarchy buy us? We have an immutable deque which can contain one, two, three or four elements, and that's all. Useful? Yes.&lt;/P&gt;
&lt;P&gt;Here's my new recursive definition of a deque: a deque of T's is:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;empty, or 
&lt;LI&gt;a single element of type T, or 
&lt;LI&gt;a left dequelette of T, followed by a middle &lt;STRONG&gt;deque of dequelettes of T&lt;/STRONG&gt;, followed by a right dequelette of T.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That bit in boldface is the key. The cold storage in the middle is NOT another deque &lt;STRONG&gt;of items&lt;/STRONG&gt;, it is a deque &lt;STRONG&gt;of dequelettes of items&lt;/STRONG&gt;. (In particular in this implementation it will furthermore be a deque of dequelettes where every dequelette is of size three. Each item in the cold storage holds &lt;EM&gt;three&lt;/EM&gt; items of the outer deque.)&lt;/P&gt;
&lt;P&gt;This use of the type system may be a bit confusing. Let's draw it out. Without loss of generality, let's suppose that we're enqueuing 1, 2, 3, 4, ... onto the right hand side of a deque, starting with the empty deque. The structures we built up go like this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Deque&amp;lt;int&amp;gt;.Empty&lt;BR&gt;Deque&amp;lt;int&amp;gt;.SingleDeque (1)&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Empty -- One(2) )&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Empty -- Two(2, 3) )&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Empty -- Three(2, 3, 4) )&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Empty -- Four(2, 3, 4, 5) )&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Now at this point we are about to enqueue 6, but there is no more room on the cheap storage at the right&amp;nbsp;endpoint. We need to make more room, so let's take three of those out of there, make a dequelette out of them, and stuff them into the right hand side of the cold storage. Notice that the thing in the middle is a single-element deque which contains a dequelette. It is &lt;EM&gt;not&lt;/EM&gt; a three-element deque of integers:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Single (Three(2, 3, 4) ) -- Two(5, 6))&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Single (Three(2, 3, 4) ) -- Three(5, 6, 7))&lt;BR&gt;Deque&amp;lt;int&amp;gt;( One(1) -- Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Single (Three(2, 3, 4) ) -- Four(5, 6, 7, 8))&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Again, as we are about to enqueue 9, we're out of space in the cheap seats. Move stuff into cold storage. That causes the cold storage to go from a single-element deque to a two-element deque. Note the type of the innermost middle empty element is a deque of dequelettes, where each dequelette contains three dequelettes, each of which contains three ints. So the innermost cold storage will be storing &lt;EM&gt;nine items per node when eventually we start pushing stuff into it.&lt;/EM&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Deque&amp;lt;int&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; One(1) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; One(Three(2, 3, 4))&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Deque&amp;lt;Deque&amp;lt;Deque&amp;lt;int&amp;gt;.Dequelette&amp;gt;.Dequelette&amp;gt;.Empty&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; One(Three(5, 6, 7)))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Two(8, 9))&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;Our last example was inefficient. Is this efficient? &lt;/P&gt;
&lt;P&gt;When enqueueing, most of the time the operation is cheap, just creating a new dequelette. Every third enqueue is expensive; it requires us to do two operations: first, to turn a four-dequelette into a two-dequelette, and second, to create a three dequelette and enqueue it into the cold storage. Every ninth enqueue causes the cold storage to itself have to do an expensive operation on its cold storage. And every twenty-seventh operation requires... and so on.&amp;nbsp; If you sum up that series, you find that the most &lt;EM&gt;expensive possible operation&lt;/EM&gt; costs O(log n), but those are so few and far between that the &lt;EM&gt;average cost of enqueueing each element&lt;/EM&gt; is O(1). Which is &lt;EM&gt;awesome&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;The other objection that my psychic powers are picking up on is "holy goodness, what horrors must that be wrecking upon the type system?" Relax. The generic type system is plenty buff enough to handle this. Remember, it's a logarithmic thing. A deque with a &lt;EM&gt;million&lt;/EM&gt; integers in it will have a &lt;SPAN class=code&gt;Deque&amp;lt;Deque&amp;lt;Deque&amp;lt;... &amp;lt;int&amp;gt;...&amp;gt;&lt;/SPAN&gt; no more than, say, &lt;EM&gt;twenty&lt;/EM&gt; deep. The generic type system is plenty buff enough to handle a recursively defined generic type a mere twenty levels deep.&lt;/P&gt;
&lt;P&gt;Also, remember, this is a generic type, not a C++ template. All the code for that crazy generic type is generated &lt;STRONG&gt;once&lt;/STRONG&gt; by the jitter, and then the &lt;EM&gt;same&lt;/EM&gt; code is shared for every reference constructed type where the type argument is a reference type -- which in this case, is all of them. That's the great thing about generic types; because they guarantee at compile time that everything in the implementation will work out at runtime, &lt;STRONG&gt;the code can be reused&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;What about dequeueing? Same deal. When the cheap storage on the end points gets down to a single element dequelette, just dequeue a three-dequelette from the code storage and use that as the new cheap storage. Again, &lt;STRONG&gt;at least&lt;/STRONG&gt; &lt;STRONG&gt;two thirds of all operations are cheap&lt;/STRONG&gt; and the price of the expensive ones grows slowly, so the &lt;EM&gt;amortized&lt;/EM&gt; cost of each dequeue is constant.&lt;/P&gt;
&lt;P&gt;As a more advanced topic, which I may come back to at some point in the future, we can also implement cheap &lt;STRONG&gt;concatenation&lt;/STRONG&gt; of two deques if we allow the cold storage to hold both twos and threes, instead of just threes. I have an implementation but the code for that gets really quite tedious, so I won't show it here. Using twos or threes makes it potentially slightly more expensive than just using threes because you go from a guarantee of two thirds of the operations being cheap to only half being cheap. But on average the amortized cost is still constant per operation whether it is twos or threes.&lt;/P&gt;
&lt;P&gt;If you're still having trouble grasping the details of this data structure, try drawing out all the references on a whiteboard. You get a very odd tree-like structure. With most trees, the nodes "in the middle" are the "obvious" ones because they are near the root. In this tree structure (and it is a tree structure in the final analysis!) its the &lt;EM&gt;leaf notes near the edges&lt;/EM&gt; which are the most "shallow" nodes. The middle is where the tree gets "deeper". This is exactly what you want for a structure where the stuff on the edges needs to be cheap to access compared to the stuff in the middle.&lt;/P&gt;
&lt;P&gt;Incidentally, this kind of tree is an example of a "finger tree". The "fingers" are the special references to the various special "edge" nodes.&lt;/P&gt;
&lt;P&gt;We could keep on going and talking about more and more advanced analysis of immutable structures, but I think I'll stop here. This gives the flavour of this style of programming pretty well I think, so no need to labour the point further.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Acknowledgements:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;One of the reasons I write about this stuff is because it forces me to learn about it. I learned a lot, and I hope you did too. For this series, I am indebted to Chris Okasaki's excellent book "Purely Functional Data Structures"; the thesis it was based upon is &lt;A href="http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf" mce_href="http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf"&gt;here&lt;/A&gt;.&amp;nbsp; Also to Ralf Hinze and Ross Paterson's &lt;A href="http://www.soi.city.ac.uk/~ross/papers/FingerTree.pdf" mce_href="http://www.soi.city.ac.uk/~ross/papers/FingerTree.pdf"&gt;excellent paper on finger trees&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Coming up next&lt;/STRONG&gt;: I'm not exactly sure. I have a pretty kick-ass implementation of some very fun algorithms which demonstrate the &lt;EM&gt;practical&lt;/EM&gt; advantages of programming in an immutable style. Or perhaps I'll change gears a bit and talk about something else entirely. Either way, it'll be a fabulous adventure I'm sure.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7656893" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part 10: A double-ended queue</title><link>http://blogs.msdn.com/ericlippert/archive/2008/01/22/immutability-in-c-part-10-a-double-ended-queue.aspx</link><pubDate>Tue, 22 Jan 2008 18:15:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7191262</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>28</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7191262.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7191262</wfw:commentRss><description>&lt;div class="mine"&gt; &lt;p&gt;Based on the comments, the implementation of a single-ended queue as two stacks was somewhat mind-blowing for a number of readers. People, you ain't seen nothing yet.&lt;/p&gt; &lt;p&gt;Before we get into the actual bits and bytes of the solution, think for a bit about how you might implement an immutable queue which could act like both a stack or a queue at any time. You can think of a stack as "it goes on the left end, it comes off the left end", and a queue as "it goes on the left end, it comes off the right end". Now we want "it goes on and comes off either end". For short, we'll call a double ended queue a "deque" (pronounced "deck"), and give our immutable deque this interface:&lt;/p&gt;&lt;span class="code"&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IDeque&amp;lt;T&amp;gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T PeekLeft();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T PeekRight();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDeque&amp;lt;T&amp;gt; EnqueueLeft(T value);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDeque&amp;lt;T&amp;gt; EnqueueRight(T value);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDeque&amp;lt;T&amp;gt; DequeueLeft();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDeque&amp;lt;T&amp;gt; DequeueRight();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool IsEmpty { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt; &lt;h5&gt;Attempt #1&lt;/h5&gt; &lt;p&gt;We built a single-ended queue out of two stacks. Can we pull a similar trick here?&amp;nbsp; How about we have the "left stack" and the "right stack". Enqueuing on the left pushes on the left stack, enqueuing on the right pushes on the right stack, and so on.&lt;/p&gt; &lt;p&gt;Unfortunately, this has some problems. What if you are dequeuing on the right and you run out of items on the right-hand stack?&amp;nbsp; Well, no problem, we'll pull the same trick as before -- reverse the left stack and swap it with the right stack.&lt;/p&gt; &lt;p&gt;The trouble with that is, suppose the left stack is { 1000, 999, ..., 3, 2, 1 } and the right stack is empty. Someone dequeues the deque on the right. We reverse the stack, swap them and pop the new right stack. Now we have an empty left-hand stack and { 2, 3, 4, .... 1000 } on the right hand stack. It took 1000 steps to do this. Now someone tries to dequeue on the left. We reverse the right queue, swap, and pop, and now we have { 999, 998, ... 3, 2 }.&amp;nbsp; That took 999 steps. If we keep on dequeuing alternating on the right and left we end up doing on average &lt;strong&gt;five hundred pushes per step&lt;/strong&gt;. That's terrible performance. Clearly this is an O(n&lt;sup&gt;2&lt;/sup&gt;) algorithm.&lt;/p&gt; &lt;h5&gt;Attempt #2&lt;/h5&gt; &lt;p&gt;Our attempt to model this as a pair of stacks seems to be failing. Let's take a step back and see if we can come up with a recursively defined data structure which makes it more apparent that there is &lt;strong&gt;cheap access to each end. &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The standard recursive definition of a stack is "a stack is either empty, or an item (the head) followed by a stack (the tail)". It seems like we ought to be able to say "a deque is either empty, or an item (the left) followed by a deque (the middle) followed by an item (the right)". &lt;/p&gt; &lt;p&gt;Perhaps you have already seen the problem with this definition; a deque by this definition always has an even number of elements! But we can fix that easily enough.&amp;nbsp; A deque is:&lt;/p&gt; &lt;p&gt;1) empty, or&lt;br&gt;2) a single item, or&lt;br&gt;3) a left item followed by a middle deque followed by a right item.&lt;/p&gt; &lt;p&gt;Awesome. Let's implement it.&lt;/p&gt;&lt;span class="code"&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // WARNING: THIS IMPLEMENTATION IS AWFUL. DO NOT USE THIS CODE.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public sealed class Deque&amp;lt;T&amp;gt; : IDeque&amp;lt;T&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private sealed class EmptyDeque : IDeque&amp;lt;T&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return 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; public IDeque&amp;lt;T&amp;gt; EnqueueLeft(T value) { return new SingleDeque(value); }&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; public IDeque&amp;lt;T&amp;gt; EnqueueRight(T value) { return new SingleDeque(value); }&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; public IDeque&amp;lt;T&amp;gt; DequeueLeft() { throw new Exception("empty deque"); }&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; public IDeque&amp;lt;T&amp;gt; DequeueRight() { throw new Exception("empty deque"); }&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; public T PeekLeft () { throw new Exception("empty deque"); }&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; public T PeekRight () { throw new Exception("empty deque"); }&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; private sealed class SingleDeque : IDeque&amp;lt;T&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public SingleDeque(T t) { item = t; }&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; private readonly T item;&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; public bool IsEmpty { get { return false; } }&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; public IDeque&amp;lt;T&amp;gt; EnqueueLeft(T value) { return new Deque&amp;lt;T&amp;gt;(value, Empty, item); }&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; public IDeque&amp;lt;T&amp;gt; EnqueueRight(T value) { return new Deque&amp;lt;T&amp;gt;(item, Empty, value); }&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; public IDeque&amp;lt;T&amp;gt; DequeueLeft() { return Empty; }&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; public IDeque&amp;lt;T&amp;gt; DequeueRight() { return Empty; }&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; public T PeekLeft () { return item; }&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; public T PeekRight () { return item; }&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; private static readonly IDeque&amp;lt;T&amp;gt; empty = new EmptyDeque();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IDeque&amp;lt;T&amp;gt; Empty { get { return empty; } }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return false; } }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Deque(T left, IDeque&amp;lt;T&amp;gt; middle, T right)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.left = left;&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; this.middle = middle;&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; this.right = right;&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; private readonly T left;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IDeque&amp;lt;T&amp;gt; middle;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly T right;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IDeque&amp;lt;T&amp;gt; EnqueueLeft(T value) &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new Deque&amp;lt;T&amp;gt;(value, middle.EnqueueLeft(left), right);&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; public IDeque&amp;lt;T&amp;gt; EnqueueRight(T value) &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new Deque&amp;lt;T&amp;gt;(left, middle.EnqueueRight(right), value);&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; public IDeque&amp;lt;T&amp;gt; DequeueLeft() &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (middle.IsEmpty) return new SingleDeque(right);&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; return new Deque&amp;lt;T&amp;gt;(middle.PeekLeft(), middle.DequeueLeft(), right);&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; public IDeque&amp;lt;T&amp;gt; DequeueRight() &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (middle.IsEmpty) return new SingleDeque(left);&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; return new Deque&amp;lt;T&amp;gt;(left, middle.DequeueRight(), middle.PeekRight());&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; public T PeekLeft () { return left; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public T PeekRight () { return right; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/span&gt; &lt;p&gt;I seem to have somewhat anticipated my denouement, but this is coding, not mystery novel writing. What is so awful about this implementation? It seems like a perfectly straightforward implementation of the abstract data type. But it turns out to be actually &lt;em&gt;worse&lt;/em&gt; than the two-stack implementation we first considered. What are your thoughts on the matter?&lt;/p&gt; &lt;p&gt;Next time, what's wrong with this code and some groundwork for fixing it. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7191262" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Nine: Academic? Plus my AVL tree implementation</title><link>http://blogs.msdn.com/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx</link><pubDate>Tue, 22 Jan 2008 03:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7190590</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7190590.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7190590</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Good Monday morning all. I have received a lot of good comments on this series so far that I thought I would speak to a bit.&lt;/P&gt;
&lt;H5&gt;Academic?&lt;/H5&gt;
&lt;P&gt;First and foremost, a number of people have asked questions which could be summed up as "isn't this just an academic exercise? I have a job to do here!"&lt;/P&gt;
&lt;P&gt;No, I do not believe that it is just an academic exercise, not at all. When I compare the practical, solving-real-problems code I write using immutable or ("mostly" immutable objects) to that which uses highly mutable objects, I find that the solutions which use immutable objects are easier to reason about. Knowing that an object isn't going to be "edited" by some other bit of code later on means that anything I deduce about it now is going to continue to be true forever. &lt;/P&gt;
&lt;P&gt;I also find that programming in a more "functional" style using immutable objects somehow encourages me to write very small, clear methods that each do one thing very well. This is certainly possible when writing code with mutable objects, but I find that something about writing code for immutable objects encourages that style more. I haven't managed to quite figure out why that is yet. I like that style of programming a lot. Take a look at the short little methods below, for, say, tree rotation. Each of them is about four lines long and obviously correct if you read it carefully. That gives you confidence that those rotation helpers can then be composed to make a correct balancer, which gives you confidence that the tree is balanced.&lt;/P&gt;
&lt;P&gt;Another reason why immutable objects tend to be easier to reason about is that this style encourages non-nullable programming. Take a look at the code from the previous entries in this series. The keyword "null" does not appear in any of them! And why should it? Why &lt;EM&gt;should&lt;/EM&gt; we represent an empty stack the same way we represent an empty queue, the same way we represent an empty tree? By ensuring that everything which points to something else is never null, all that boring, slow, hard to read, hard to reason about code which checks to see if things are null just goes away. You need never worry whether that reference is null again if you design your objects so that there's never a null reference in the first place.&lt;/P&gt;
&lt;P&gt;And as we'll see in later episodes of FAIC, immutable objects also make it easier to implement performance improvements such as memoization of complex calculations. If an object never changes then you can always cache it for reuse later. An object which someone can edit is less useful that way. Immutable objects stored in a stack make undo-redo operations trivial. And so on.&lt;/P&gt;
&lt;P&gt;Learning how to use this style in your own code is therefore potentially quite handy. I believe it is also the case that more and more objects produced by other people will be immutable, so knowing how to deal with them will be increasingly important. For example, the objects which represent expression trees in C# 3.0 are all immutable. If you want to take an expression tree and transform it, you're simply not going to be able to transform it "in place". You're going to have to build a new expression tree out of the old one; knowing how to do so efficiently will help.&lt;/P&gt;
&lt;H5&gt;Thread safe?&lt;/H5&gt;
&lt;P&gt;The second question I've gotten a lot is "are immutable objects really more thread safe?" Well, it depends on what you mean by "thread safe". Immutable objects are not necessarily "more" thread safe, but they're a different kind of thread safe.&lt;/P&gt;
&lt;P&gt;Let's explore this a bit more. What exactly do we mean by "thread safe"? We can talk about lock order and deadlocks and all of those aspects of thread safety, but let's put those aside for a moment and just consider basic race conditions. Suppose you have two threads each enqueuing jobs onto a queue object, and a third thread dequeuing jobs. Normally we think of the queue as being "thread safe" if no matter what the timing of those three threads happens to be, there is no way that a job is ever "lost". Two enqueues which happen "at the same time" result in a queue with those two things on it, and at some point, both will be dequeued.&lt;/P&gt;
&lt;P&gt;If the queue is immutable then implementing this scenario just moves the problem around; now it becomes about serializing access to the mutable variable which is being shared by all three threads. Immutable objects make this kind of scenario harder to reason about and implement; &lt;STRONG&gt;better to just write a threadsafe mutable queue in the first place if that's the problem you're trying to solve.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;But let's think about this a different way. Having a threadsafe mutable queue means that you never have any accurate information whatsoever about the state of the queue! You ask the queue "are you empty?" and it says "no", and you dequeue it and hey, you get an "empty queue" exception. Why? Because some other thread dequeued it in the time between when you asked and when you issued your dequeue request. You end up living in a world where enqueuing a queue can possibly make it shorter and dequeuing can make it longer depending on what is going on with other threads. It becomes impossible to reason locally about operations on an object; your consciousness has to expand to encompass all possible operations on the object. It's this necessity for global understanding that makes multithreaded programming so error-prone and difficult.&lt;/P&gt;
&lt;P&gt;Immutable queues, on the other hand, give you complete thread safety in this regard. You enqueue an element onto a particular immutable queue and the result you get back is always the same no matter what is happening to that queue on any other thread. You ask a queue if it is empty, if it says no, then you have a 100% iron-clad guarantee that you can safely dequeue it. You can share data around threads as much as you like without worrying that some other thread is going to make an edit which messes up your logic. You can take a chunk of data and run ten different analyzers over it on ten different threads, each one making "changes" to the data during its analysis, and never interfering with each other.&lt;/P&gt;
&lt;H5&gt;AVL Tree implementation&lt;/H5&gt;
&lt;P&gt;As promised last time, my supremely unexciting implementation of a self-balancing height-balanced immutable AVL tree in C#. Note that I have made the choice to cache the height in every node rather than recalculating it. That trades memory usage for a bit of extra speed, which is probably worth it in this case. (Though of course to truly answer the question we'd want to set goals, try it both ways and measure the results.)&lt;/P&gt;
&lt;P&gt;This is all pretty straightforward. Next time I want to start to wrap up this series by looking at a tricky data structure that solves the problem of building an immutable double-ended queue.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;SPAN class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public sealed class AVLTree&amp;lt;K, V&amp;gt; : IBinarySearchTree&amp;lt;K, V&amp;gt; where K : IComparable&amp;lt;K&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private sealed class EmptyAVLTree : IBinarySearchTree&amp;lt;K, V&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // IBinaryTree&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; public bool IsEmpty { get { return 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; public V Value { get { throw new Exception("empty tree"); } }&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; IBinaryTree&amp;lt;V&amp;gt; IBinaryTree&amp;lt;V&amp;gt;.Left { get { throw new Exception("empty tree"); } }&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; IBinaryTree&amp;lt;V&amp;gt; IBinaryTree&amp;lt;V&amp;gt;.Right { get { throw new Exception("empty tree"); } }&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; // IBinarySearchTree&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Left { get { throw new Exception("empty tree"); } }&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Right { get { throw new Exception("empty tree"); } }&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Search(K key) { return this; }&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; public K Key { get { throw new Exception("empty tree"); } }&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Add(K key, V value) { return new AVLTree&amp;lt;K, V&amp;gt;(key, value, this, this); }&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Remove(K key) { throw new Exception("Cannot remove item that is not in tree."); }&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; // IMap&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; public bool Contains(K key) { return false; }&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; public V Lookup(K key) { throw new Exception("not found"); }&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; IMap&amp;lt;K, V&amp;gt; IMap&amp;lt;K, V&amp;gt;.Add(K key, V value) { return this.Add(key, value); }&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; IMap&amp;lt;K, V&amp;gt; IMap&amp;lt;K, V&amp;gt;.Remove(K key) { return this.Remove(key); }&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; public IEnumerable&amp;lt;K&amp;gt; Keys { get { yield break; } }&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; public IEnumerable&amp;lt;V&amp;gt; Values { get { yield break; } }&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; public IEnumerable&amp;lt;KeyValuePair&amp;lt;K,V&amp;gt;&amp;gt; Pairs { get { yield break; } }&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; private static readonly EmptyAVLTree empty = new EmptyAVLTree();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IBinarySearchTree&amp;lt;K, V&amp;gt; Empty { get { return empty; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly K key;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly V value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinarySearchTree&amp;lt;K, V&amp;gt; left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinarySearchTree&amp;lt;K, V&amp;gt; right;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly int height;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private AVLTree(K key, V value, IBinarySearchTree&amp;lt;K, V&amp;gt; left, IBinarySearchTree&amp;lt;K, V&amp;gt; right)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.key = key;&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; this.value = value;&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; this.left = left;&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; this.right = right;&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; this.height = 1 + Math.Max(Height(left), Height(right));&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; // IBinaryTree&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return false; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Value { get { return value; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; IBinaryTree&amp;lt;V&amp;gt;.Left { get { return left; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; IBinaryTree&amp;lt;V&amp;gt;.Right { get { return right; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // IBinarySearchTree&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinarySearchTree&amp;lt;K, V&amp;gt; Left { get { return left; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinarySearchTree&amp;lt;K, V&amp;gt; Right { get { return right; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinarySearchTree&amp;lt;K, V&amp;gt; Search(K key)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int compare = key.CompareTo(Key);&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 (compare == 0)&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; return this;&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; else if (compare &amp;gt; 0)&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; return Right.Search(key);&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; else&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; return Left.Search(key);&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; public K Key { get { return key; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinarySearchTree&amp;lt;K, V&amp;gt; Add(K key, V value)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AVLTree&amp;lt;K, V&amp;gt; result;&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 (key.CompareTo(Key) &amp;gt; 0)&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; result = new AVLTree&amp;lt;K, V&amp;gt;(Key, Value, Left, Right.Add(key, value));&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; else&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; result = new AVLTree&amp;lt;K, V&amp;gt;(Key, Value, Left.Add(key, value), Right);&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; return MakeBalanced(result);&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; public IBinarySearchTree&amp;lt;K, V&amp;gt; Remove(K key)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinarySearchTree&amp;lt;K, V&amp;gt; result;&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; int compare = key.CompareTo(Key);&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 (compare == 0)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We have a match. If this is a leaf, just remove it &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; // by returning Empty.&amp;nbsp; If we have only one child,&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; // replace the node with the child.&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; if (Right.IsEmpty &amp;amp;&amp;amp; Left.IsEmpty)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = Empty;&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; else if (Right.IsEmpty &amp;amp;&amp;amp; !Left.IsEmpty)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = Left;&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; else if (!Right.IsEmpty &amp;amp;&amp;amp; Left.IsEmpty)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = Right;&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; else&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; {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We have two children. Remove the next-highest node and replace&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this node with it.&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinarySearchTree&amp;lt;K, V&amp;gt; successor = Right;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (!successor.Left.IsEmpty)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; successor = successor.Left;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new AVLTree&amp;lt;K, V&amp;gt;(successor.Key, successor.Value, Left, Right.Remove(successor.Key));&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; }&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; else if (compare &amp;lt; 0)&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; result = new AVLTree&amp;lt;K, V&amp;gt;(Key, Value, Left.Remove(key), Right);&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; else&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; result = new AVLTree&amp;lt;K, V&amp;gt;(Key, Value, Left, Right.Remove(key));&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; return MakeBalanced(result);&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; // IMap&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool Contains(K key) { return !Search(key).IsEmpty; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMap&amp;lt;K, V&amp;gt; IMap&amp;lt;K, V&amp;gt;.Add(K key, V value) { return this.Add(key, value); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMap&amp;lt;K, V&amp;gt; IMap&amp;lt;K, V&amp;gt;.Remove(K key) { return this.Remove(key); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Lookup(K key)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinarySearchTree&amp;lt;K, V&amp;gt; tree = Search(key);&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 (tree.IsEmpty)&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 Exception("not found");&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; return tree.Value;&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; public IEnumerable&amp;lt;K&amp;gt; Keys { get { return from t in Enumerate() select t.Key; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;V&amp;gt; Values { get { return from t in Enumerate() select t.Value; } &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; public IEnumerable&amp;lt;KeyValuePair&amp;lt;K,V&amp;gt;&amp;gt; Pairs &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get &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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return from t in Enumerate() select new KeyValuePair&amp;lt;K, V&amp;gt;(t.Key, t.Value);&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; private IEnumerable&amp;lt;IBinarySearchTree&amp;lt;K, V&amp;gt;&amp;gt; Enumerate()&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var stack = Stack&amp;lt;IBinarySearchTree&amp;lt;K,V&amp;gt;&amp;gt;.Empty;&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; for (IBinarySearchTree&amp;lt;K,V&amp;gt; current = this; !current.IsEmpty || !stack.IsEmpty; current = current.Right)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (!current.IsEmpty)&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; {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack = stack.Push(current);&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; current = current.Left;&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; }&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; current = stack.Peek();&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; stack = stack.Pop();&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; yield return current;&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; // Static helpers for tree balancing&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static int Height(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.IsEmpty)&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; return 0;&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; return ((AVLTree&amp;lt;K,V&amp;gt;)tree).height;&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; private static IBinarySearchTree&amp;lt;K, V&amp;gt; RotateLeft(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.Right.IsEmpty)&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; return tree;&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; return new AVLTree&amp;lt;K, V&amp;gt;( tree.Right.Key, tree.Right.Value,&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; new AVLTree&amp;lt;K, V&amp;gt;(tree.Key, tree.Value, tree.Left, tree.Right.Left),&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; tree.Right.Right);&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; private static IBinarySearchTree&amp;lt;K, V&amp;gt; RotateRight(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.Left.IsEmpty)&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; return tree;&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; return new AVLTree&amp;lt;K, V&amp;gt;( tree.Left.Key, tree.Left.Value, tree.Left.Left,&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; new AVLTree&amp;lt;K, V&amp;gt;(tree.Key, tree.Value, tree.Left.Right, tree.Right));&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; private static IBinarySearchTree&amp;lt;K, V&amp;gt; DoubleLeft(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.Right.IsEmpty)&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; return tree;&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; AVLTree&amp;lt;K, V&amp;gt; rotatedRightChild = new AVLTree&amp;lt;K, V&amp;gt;(tree.Key, tree.Value, tree.Left, RotateRight(tree.Right));&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; return RotateLeft(rotatedRightChild);&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; private static IBinarySearchTree&amp;lt;K, V&amp;gt; DoubleRight(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.Left.IsEmpty)&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; return tree;&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; AVLTree&amp;lt;K, V&amp;gt; rotatedLeftChild = new AVLTree&amp;lt;K, V&amp;gt;(tree.Key, tree.Value, RotateLeft(tree.Left), tree.Right);&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; return RotateRight(rotatedLeftChild);&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; private static int Balance(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.IsEmpty)&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; return 0;&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; return Height(tree.Right) - Height(tree.Left);&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; private static bool IsRightHeavy(IBinarySearchTree&amp;lt;K, V&amp;gt; tree) { return Balance(tree) &amp;gt;= 2; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static bool IsLeftHeavy(IBinarySearchTree&amp;lt;K, V&amp;gt; tree) { return Balance(tree) &amp;lt;= -2; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static IBinarySearchTree&amp;lt;K, V&amp;gt; MakeBalanced(IBinarySearchTree&amp;lt;K, V&amp;gt; tree)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinarySearchTree&amp;lt;K, V&amp;gt; result;&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 (IsRightHeavy(tree))&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (IsLeftHeavy(tree.Right))&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = DoubleLeft(tree);&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; else&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = RotateLeft(tree);&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; else if (IsLeftHeavy(tree))&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (IsRightHeavy(tree.Left))&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = DoubleRight(tree);&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; else&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = RotateRight(tree);&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; else&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; result = tree;&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; return result;&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;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7190590" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Eight: Even More On Binary Trees</title><link>http://blogs.msdn.com/ericlippert/archive/2008/01/18/immutability-in-c-part-eight-even-more-on-binary-trees.aspx</link><pubDate>Fri, 18 Jan 2008 22:02:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7152019</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/7152019.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=7152019</wfw:commentRss><description>&lt;div class="mine"&gt; &lt;p&gt;Last year we declared a relatively simple interface to represent an immutable binary tree. We noticed that it was different from every other interface that we've declared so far, in that it really said nothing at all about the immutability of the tree. One normally thinks of immutable data types not in terms of their &lt;em&gt;shape&lt;/em&gt;, but rather in terms of what &lt;em&gt;operations&lt;/em&gt; may be performed on the data type. Operations are usually either to query the object somehow, or to "modify" it by producing new modified versions of the old immutable object.&lt;/p&gt; &lt;p&gt;This binary tree interface is also unsatisfying because it does not address a &lt;em&gt;problem&lt;/em&gt; to be solved (other than "organize this data into a binary tree", I suppose.) It seems to be a solution in search of a problem. So let's find a problem and build a better binary tree to solve that problem.&lt;/p&gt; &lt;p&gt;The problem I want to consider today is the implementation of immutable "dictionaries" or "maps". That is, objects which allow you to store a list of "keys" and their associated "values", and then rapidly look up the value associated with the key. Here's a reasonable definition for an immutable dictionary interface:&lt;/p&gt;&lt;span class="code"&gt; &lt;p&gt;public interface IMap&amp;lt;K, V&amp;gt; where K : IComparable&amp;lt;K&amp;gt;&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool Contains(K key);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; V Lookup(K key);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMap&amp;lt;K, V&amp;gt; Add(K key, V value);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMap&amp;lt;K, V&amp;gt; Remove(K key);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;K&amp;gt; Keys { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;V&amp;gt; Values { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;KeyValuePair&amp;lt;K,V&amp;gt;&amp;gt; Pairs { get; }&lt;br&gt;} &lt;/span&gt; &lt;p&gt;Now, we could easily implement this interface by, say, inventing a class which holds on to an immutable stack of pairs. When you want to add a pair, just push it on to the stack. To find a pair, just enumerate the stack, comparing each key as you go. To remove an item, pop every item off the old stack and onto a new stack, skipping the item to remove.&lt;/p&gt; &lt;p&gt;That would fulfill the contract, but the obvious problem with this approach is that adding is cheap, but removal and searching become O(n) for a dictionary containing n items. A stack-based dictionary with ten thousand items takes between 1 and 10000 comparisons to find an item (and always takes the full 10000 if the item is not found.) &lt;/p&gt; &lt;p&gt;You could optimize this somewhat by keeping the stack sorted... except, oh, that then makes insertion O(n) as well, and lookups really only get faster in the case where you are looking up something that isn't there that happens to come early in the list. When you get to something bigger than it, you can fail then. But lookups for things at the end of the list are still potentially slow.&lt;/p&gt; &lt;p&gt;We can do a lot better than that if we organize the pairs into a binary tree sorted so that every keys in the left subtree is not greater than every key in the right subtree. Such a tree is (for obvious reasons) called a &lt;strong&gt;binary search tree.&lt;/strong&gt; We can define a new contract for it which says that this has the shape of a binary tree of values, but also may be treated as a map:&lt;/p&gt;&lt;span class="code"&gt; &lt;p&gt;public interface IBinarySearchTree&amp;lt;K, V&amp;gt; : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt;, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMap&amp;lt;K, V&amp;gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; where K : IComparable&amp;lt;K&amp;gt;&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; K Key { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new IBinarySearchTree&amp;lt;K, V&amp;gt; Left { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new IBinarySearchTree&amp;lt;K, V&amp;gt; Right { get; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new IBinarySearchTree&amp;lt;K, V&amp;gt; Add(K key, V value);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new IBinarySearchTree&amp;lt;K, V&amp;gt; Remove(K key);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinarySearchTree&amp;lt;K, V&amp;gt; Search(K key);&lt;br&gt;} &lt;/span&gt;&lt;/p&gt; &lt;p&gt;But how on earth are we going to insert a node into a binary &lt;em&gt;search&lt;/em&gt; tree? Since an immutable binary tree has got to be built "from the leaves", aren't we going to have to rebuild the entire tree every time we insert a node? (Without loss of generality, assume that the item is not in the tree already. We'll discuss what to do in that situation later.)&lt;/p&gt; &lt;p&gt;Let's think about it. If the tree is empty, then insertion is trivial -- you just return a new single-node tree.&lt;/p&gt; &lt;p&gt;If the tree is not empty, then either the new element fits in the right subtree or the left subtree. Suppose it's the right. Then you do not have to rebuild any of the left subtree, only the root node and the right subtree. That eliminates half of the possible work right there! But that then is true of the right subtree as well -- either it is trivial, or half of its work will be eliminated immediately. We keep on eliminating half the work every time, and 1/2 + 1/4 + 1/8 + ... gets pretty darn close to "all the work".&lt;/p&gt; &lt;p&gt;Awesome. Or, perhaps not.&lt;/p&gt; &lt;p&gt;Remember, it is perfectly legal to have a binary search tree where &lt;strong&gt;every left subtree is empty&lt;/strong&gt;. You just have a long, long train of trees down the right hand side. Essentially what you have is the sorted stack that we had before. Inserting a new item at the bottom would require building the whole tree again. &lt;strong&gt;Eliminating the&lt;/strong&gt; &lt;strong&gt;left hand side only eliminates half the work if half the nodes are on the left hand side!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;But suppose we had a way to guarantee that these sorts of pathological situations never happened. What then would the cost of inserting an item into a binary tree be? Clearly the cost of inserting the node is the cost of generating O(h) new tree nodes, where h is the depth at which the new node is inserted. Therefore, all we need to do in order to keep insertion relatively cheap is to keep the tree height as small as possible everywhere. Such a tree is called a &lt;strong&gt;balanced binary tree&lt;/strong&gt;, and there are lots of ways to balance a binary tree. You can balance a tree by guaranteeing that the left side has some fraction of the total nodes (a "weight balanced tree") or that the height of the left side is less than some multiplier of the height of the right side, or that the left and right heights differ by less than some constant (a height balanced tree).&lt;/p&gt; &lt;p&gt;I don't want this to turn into a tutorial on tree balancing; there are plenty of web sites out there that can discuss the intricacies of tree rotations for height balancing. So tell you what, anyone who is interested, read the &lt;a href="http://en.wikipedia.org/wiki/AVL_tree"&gt;wikipedia page on AVL tree balancing&lt;/a&gt;, and next time on FAIC I'll post an implementation of an immutable height-balanced AVL tree which implements the contract above.&lt;/p&gt; &lt;p&gt;(This is pretty straightforward stuff; the immutable queue was slightly mind-blowing to a number of readers, but immutable balanced binary trees are just straightforward busywork. After we get through that I'll show you guys how to make a combination-stack-and-queue that can be efficiently read from &lt;strong&gt;both&lt;/strong&gt; ends, &lt;em&gt;and&lt;/em&gt; is immutable. It uses the generic type system in an interesting way to make it all work efficiently.)&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7152019" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Seven: More on Binary Trees</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/19/immutability-in-c-part-seven-more-on-binary-trees.aspx</link><pubDate>Wed, 19 Dec 2007 23:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6809314</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6809314.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6809314</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Lots of good comments on my previous post. To briefly follow up:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;One of the downsides of immutable tree implementations is that usually the tree must be built from the leaves up, which is not always convenient. We'll look at implementations which hide this fact from the user in future posts. &lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;One smartypants pointed out that sure, this tree can have cycles -- if you have &lt;EM&gt;another&lt;/EM&gt; binary tree implementation that has cycles and then paste such a cyclic tree in. True; what I meant was that &lt;EM&gt;using only the stated implementation&lt;/EM&gt;, it's impossible to create a tree with cycles. If you are hell bent on making a bad tree, you can surely do that. Again, in a future post we'll have a tree which is built up by calling tree "mutating" operations, and those really will be guaranteed acyclic even in a world where there are other bad implementations hanging around.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;And finally, one reader correctly identified the problem with my recursive implementation of in-order iteration. A tree of maximum height h ends up allocating O(h) iterator objects. The recursive calls get O(h) deep. If h is very large, this could blow the call stack. And if the tree has n nodes, each with an average height of O(h), then iterating each node will require O(h) recursive calls apiece. Therefore the total time cost in calls for iterating the entire tree is O(n h).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In a binary tree with n nodes, h is always between log n and n, so that means that this iterator has best case asymptotic performance of O(n log n) and worst case&amp;nbsp; of O(n&lt;SUP&gt;2&lt;/SUP&gt;) in time, and uses between O(log n) and O(n) in both call stack and heap space. That's pretty lousy.&lt;/P&gt;
&lt;P&gt;A better implementation would be to write a tree traversal algorithm which does not use recursion. &lt;A href="http://blogs.msdn.com/ericlippert/archive/2005/08/01/recursion-part-two-unrolling-a-recursive-function-with-an-explicit-stack.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/08/01/recursion-part-two-unrolling-a-recursive-function-with-an-explicit-stack.aspx"&gt;Use an explicit stack rather than the call stack:&lt;/A&gt;&lt;SPAN class=code&gt;&lt;/P&gt;
&lt;P&gt;public static IEnumerable&amp;lt;T&amp;gt; InOrder&amp;lt;T&amp;gt;(this IBinaryTree&amp;lt;T&amp;gt; tree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IStack&amp;lt;IBinaryTree&amp;lt;T&amp;gt;&amp;gt; stack = Stack&amp;lt;IBinaryTree&amp;lt;T&amp;gt;&amp;gt;.Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (IBinaryTree&amp;lt;T&amp;gt; current = tree; !current.IsEmpty || !stack.IsEmpty; current = current.Right)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (!current.IsEmpty)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack = stack.Push(current);&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; current = current.Left;&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; current = stack.Peek();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack = stack.Pop();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return current.Value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This consumes O(n) time, O(h) heap space, and O(1) call stack space. It is also &lt;STRONG&gt;painful&lt;/STRONG&gt; to read and analyze compared to the slow naive implementation. 
&lt;P&gt;I would very much like to add new syntax to a hypothetical future version of C# which would be a syntactic sugar for the code above. If, hypothetically, we were prioritizing features for unannounced future versions of C#, unfortunately that one would not be our highest priority, so I wouldn't expect it any time soon. &lt;A href="http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx" mce_href="http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx"&gt;My colleague Wes has written a great article that goes into more details about the problem above&lt;/A&gt; and ways we might solve it in the future, so check that out if you want the details. 
&lt;P&gt;I have the code for the next few blog posts written, but odds are good that I'm not going to have time to write the surrounding text until after the festive holiday season is over. I hope you have a wonderful time during the remainder of 2007 and we'll see you bright and early in 2008 for more fabulous adventures!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6809314" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Six: A Simple Binary Tree</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/18/immutability-in-c-part-six-a-simple-binary-tree.aspx</link><pubDate>Tue, 18 Dec 2007 22:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6798908</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6798908.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6798908</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;OK, we've gotten pretty good at this by now. A straightforward implementation of an immutable generic binary tree requires little comment on the basics. A binary tree is either empty, or a value, left tree and right tree:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool IsEmpty { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; V Value { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; Left { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; Right { get; }&lt;BR&gt;} &lt;/SPAN&gt;
&lt;P&gt;And our implementation has, as always, a singleton empty tree. One minor point is that unlike previous data structures, where the structure itself knew how to build more of the same, this one does not. There's no obvious "insert" operation in a binary tree, so we'll just leave it up to the implementer. (A binary tree is essentially defined by its &lt;EM&gt;shape&lt;/EM&gt;, not by the operations one can perform on it.) In this case, we'll just make a constructor:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public sealed class BinaryTree&amp;lt;V&amp;gt; : IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private sealed class EmptyBinaryTree : IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return true; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Left { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Right { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Value { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static readonly EmptyBinaryTree empty = new EmptyBinaryTree();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IBinaryTree&amp;lt;V&amp;gt; Empty { get { return empty; } }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly V value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinaryTree&amp;lt;V&amp;gt; left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinaryTree&amp;lt;V&amp;gt; right; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return false; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Value { get { return value; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Left { get { return left; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Right { get { return right; } } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public BinaryTree(V value, IBinaryTree&amp;lt;V&amp;gt; left, IBinaryTree&amp;lt;V&amp;gt; right)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.value = value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.left = left ?? Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.right = right ?? Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Note that another nice feature of immutable data structures is that &lt;STRONG&gt;it&lt;/STRONG&gt; &lt;STRONG&gt;is impossible to accidentally (or deliberately!) create a tree which contains a cycle&lt;/STRONG&gt;. In a mutable tree you could do something stupid like making the root a child of one of the leaves (or, for that matter, a child of itself!) Then you have to either live with the possibility that a user will create a cyclic "tree" and hope for the best (or, in other words, crash and/or hang) or you have to build yourself a cycle detector. Cycle detectors have potentially serious performance implications. It may be best to simply prevent the situation from arising in the first place.&lt;/P&gt;
&lt;P&gt;A feature conspicuous by its absence from the above implementation is enumeration. Unlike a stack or a queue, there's no obvious best order in which to enumerate the members a binary tree. First off, there's the question of whether to enumerate in depth-first or breadth-first order, and then the matter of whether the parent comes before, after or between the children.&lt;/P&gt;
&lt;P&gt;We could create extension methods which did various different enumerations on a binary tree. Here is a &lt;STRONG&gt;bad implementation&lt;/STRONG&gt; of an "in order" traversal (depth first, parent comes between the children -- so-called because in a binary search tree, this enumerates the nodes in sorted order.)&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public static IEnumerable&amp;lt;V&amp;gt; InOrder&amp;lt;V&amp;gt;(this IBinaryTree&amp;lt;V&amp;gt; tree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // BAD IMPLEMENTATION, DO NOT DO THIS&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.IsEmpty) yield break;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(V v in tree.Left.InOrder()) yield return v;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return tree.Value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(V v in tree.Right.InOrder()) yield return v;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This &lt;EM&gt;seems&lt;/EM&gt; perfectly straightforward and sensible, but this implementation is actually quite flawed. We can do a lot better. What is wrong with this implementation of enumeration, and how would you fix it? (Hint: start your analysis with the assumption that the tree has maximum height h and total number of nodes n.)&lt;/P&gt;
&lt;P&gt;Next time: a better implementation of traversal, and then after that, some more complex kinds of immutable binary tree. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6798908" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Five: LOLZ!</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/13/immutability-in-c-part-five-lolz.aspx</link><pubDate>Thu, 13 Dec 2007 22:19:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6764196</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6764196.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6764196</wfw:commentRss><description>&lt;div class="mine"&gt; &lt;p&gt;My sadly soon-to-be-erstwhile coworker Cyrus made me a &lt;a href="http://lolgeeks.com/"&gt;lolgeek&lt;/a&gt; shirt to go with this series of blog articles:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ericlippert/WindowsLiveWriter/ImmutabilityinCPartFiveLOLZ_9F3B/ShirtFront_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="ShirtFront" src="http://blogs.msdn.com/blogfiles/ericlippert/WindowsLiveWriter/ImmutabilityinCPartFiveLOLZ_9F3B/ShirtFront_thumb.jpg" width="210" border="0"&gt;&lt;/a&gt; &lt;a href="http://blogs.msdn.com/blogfiles/ericlippert/WindowsLiveWriter/ImmutabilityinCPartFiveLOLZ_9F3B/ShirtBack_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="ShirtBack" src="http://blogs.msdn.com/blogfiles/ericlippert/WindowsLiveWriter/ImmutabilityinCPartFiveLOLZ_9F3B/ShirtBack_thumb.jpg" width="202" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Cyrus, needless to say, is a big goof. Thanks, dude!&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6764196" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item></channel></rss>