{"id":1543,"date":"2009-10-06T15:54:00","date_gmt":"2009-10-06T15:54:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2009\/10\/06\/hidden-costs-matt-gertz\/"},"modified":"2024-07-05T12:46:38","modified_gmt":"2024-07-05T19:46:38","slug":"hidden-costs-matt-gertz","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/hidden-costs-matt-gertz\/","title":{"rendered":"Hidden Costs (Matt Gertz)"},"content":{"rendered":"<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">(Note: there was a grievous error in this post based on a bad assumption on my art regarding VB.&nbsp; Not feeling the need to hide my ignorance :-), I have instead made a number of edits in this post to bring it back to some semblance of reality.)<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">One thing that gets me annoyed with myself is realizing that the product or service I&rsquo;ve just bought has some hidden costs that I didn&rsquo;t anticipate.<span>&nbsp; <\/span>It might be as complicated as realizing that my plane ticket has all sorts of byzantine surcharges and luggage costs, or as simple as making budgeting for a new killer gaming PC and forgetting about the sales tax &ndash; it seems that there are always extra costs out there that will come back to bite you.<span>&nbsp; <\/span>Being (as I have said in past postings to this blog) an inherently lazy person, and being fully caught up in our &ldquo;I must have the sparkly thing <i>right now<\/i>&rdquo; culture, I&rsquo;m apt to overlook the fine print in any purchase agreement unless I really force myself to slow down and pay attention to the details.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">One of the times I really have to pay attention is when I&rsquo;m reviewing code here at Microsoft.<span>&nbsp; <\/span>As a member of the release team that makes the final decisions as to what last-minute fixes are safe enough to be applied to an imminent release, it&rsquo;s my job to take a look at the proposed fix and make sure that it doesn&rsquo;t introduce more problems than it purports to solve &ndash; i.e., that it doesn&rsquo;t add hidden costs.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">On the rare occasion that I find a problem in someone&rsquo;s code, it&rsquo;s usually something that&rsquo;s obviously dysfunctional &ndash; a case where a variable isn&rsquo;t initialized properly, or where a different team has simultaneously made a change that will render this change dangerous.<span>&nbsp; <\/span>But some of the problems are more subtle, and might not be obvious if only minimal testing and review has been done.<span>&nbsp; <\/span>Consider the following code (very similar to a case I reviewed here at work the other day):<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> MyList <span>As<\/span> <span>New<\/span> <span>List<\/span>(<span>Of<\/span> <span>String<\/span>)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> Button1_Click(<span>ByVal<\/span> sender <span>As<\/span> System.<span>Object<\/span>, <span>ByVal<\/span> e <span>As<\/span> System.<span>EventArgs<\/span>) <span>Handles<\/span> Button1.Click<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> s <span>As<\/span> <span>New<\/span> System.Text.<span>StringBuilder<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> i <span>As<\/span> <span>Integer<\/span> = 0 <span>To<\/span> MyList.Count &#8211; 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>s.Append(MyList(i))<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><b>Edit<\/b>:<span>&nbsp; <\/span>This is an error in my blog post <span>&nbsp;<\/span>&ndash; I hadn&rsquo;t realized that VB, unlike many other languages, only gets the value of the stop condition once (thanks to Phil Wells for pointing this out).<span>&nbsp; <\/span>To make my point, I would have to be using code like this:<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> s <span>As<\/span> <span>New<\/span> System.Text.<span>StringBuilder<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> i <span>As<\/span> <span>Integer<\/span> = 0<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Do<\/span> <span>While<\/span> i &lt; MyList.Count() &#8211; 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>s.Append(MyList(i))<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>i += 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Loop<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\"><span>The method Count() might still have a hidden cost, but in the For Loop case, I&rsquo;m at least only hitting it once.<span>&nbsp; <\/span><\/span>The fact that VB only analyzes the stop condition once leads to a different issue to be aware of that I&rsquo;ll cover in my next blog.<\/font><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Seems pretty simple, yes?<span>&nbsp; <\/span>When a button is clicked, the code iterates through the strings in a list and appends them to a StringBuilder, creating (for whatever reason) one long string containing all of the contents.<span>&nbsp; <\/span>And, to cursory appearances, it will function correctly. <\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">However, the code has hidden costs.<span>&nbsp; <\/span>You see, written this way, the value MyList.Count is going to be reevaluated on every iteration of the &ldquo;For&rdquo; loop, even though the value itself isn&rsquo;t changing.<span>&nbsp; <\/span>Furthermore, my indexing into MyList, which is always with reference to the beginning of the list, will also have a non-zero impact.<span>&nbsp; <\/span>This impacts the performance of the code and will make my customers unhappy over the sloth-like operation of my application.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">In this case, the cost isn&rsquo;t really high, as Count() is a property wrapping something that&rsquo;s stored as a private integer member, and index referencing also has tricks to speed it up, but there&rsquo;s still a cost and it can add up.<span>&nbsp; <\/span>It&rsquo;s even worse if the Count() call has to be calculated!<span>&nbsp; <\/span>Consider this really awful code where I&rsquo;ve created my own &ldquo;List&rdquo; type:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Class<\/span> <span>MyLameObject<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; For some unknown reason, I&#8217;m creating my own linked list instead of using a List(Of) generic.<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Please don&#8217;t do this for real!<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> data <span>As<\/span> <span>String<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> NextMLO <span>As<\/span> <span>MyLameObject<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Sub<\/span> Insert(<span>ByVal<\/span> mlo <span>As<\/span> <span>MyLameObject<\/span>)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> NextMLO <span>IsNot<\/span> <span>Not\nhing<\/span> <span>Then<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NextMLO = mlo<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Else<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>mlo.NextMLO = NextMLO.NextMLO<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NextMLO.NextMLO = mlo<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End If<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Function<\/span> Count() <span>As<\/span> <span>Integer<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ct <span>As<\/span> <span>Integer<\/span> = 0<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> current <span>As<\/span> <span>MyLameObject<\/span> = <span>Me<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Do<\/span> <span>While<\/span> current <span>IsNot<\/span> <span>Nothing<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ct += 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>current = current.NextMLO<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>Loop<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> ct<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Function<\/span> Item(<span>ByVal<\/span> index <span>As<\/span> <span>Integer<\/span>) <span>As<\/span> <span>MyLameObject<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> index &gt;= Count() <span>OrElse<\/span> index &lt; 0 <span>Then<\/span> <span>Return<\/span> <span>Nothing<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> current <span>As<\/span> <span>MyLameObject<\/span> = <span>Me<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> i <span>As<\/span> <span>Integer<\/span> = 0 <span>To<\/span> index &#8211; 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>current = current.NextMLO<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> current<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Class<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> MyLameObjectHeader <span>As<\/span> <span>New<\/span> <span>MyLameObject<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> MyLameObjectHeader <span>As<\/span> <span>New<\/span> <span>MyLameObject<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> Button1_Click(<span>ByVal<\/span> sender <span>As<\/span> System.<span>Object<\/span>, <span>ByVal<\/span> e <span>As<\/span> System.<span>EventArgs<\/span>) _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Handles<\/span><span> Button1.Click<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> s <span>As<\/span> <span>New<\/span> System.Text.<span>StringBuilder<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> i <span>As<\/span> <span>Integer<\/span> = 0 <span>To<\/span> MyLameObjectHeader.Count &#8211; 1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>s.Append(MyLameObjectHeader.Item(i))<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Perhaps as a school assignment, I&rsquo;ve created a singly-linked list which contains objects of type &ldquo;MyLameObject&rdquo; (instead of using optimized collections that we provide).<span>&nbsp; <\/span>I&rsquo;ve also created a member function called &ldquo;Count&rdquo; which returns the number of objects in my list (starting from the current node) and another member function called &ldquo;Item&rdquo; which returns me a reference to a specific object in the list, as indexed from the current node.<span>&nbsp; <\/span>The code will compile and it will &ldquo;work.&rdquo;<span>&nbsp; <\/span>But, oh!<span>&nbsp;&nbsp; <\/span>It has <b>so many<\/b> hidden costs, and if the definition of MyLameObject exists in an assembly for which I don&rsquo;t have the source code, I might not even realize it!<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">First, let&rsquo;s look at button click handler.<span>&nbsp; <\/span>It&rsquo;s calling Count() on every single iteration, and there will be a number of iterations equal to the value returned from Count().<span>&nbsp; <\/span>Count(), in turn, walks the entire list every time it&rsquo;s called.<span>&nbsp; <\/span>So, that means that if my list contains 1000 items, that means that I&rsquo;ll be referencing a MyLameObject <i>one million times<\/i>!<span>&nbsp; <\/span>(This is what they refer to as an &ldquo;O(n<sup>2<\/sup>) problem&rdquo; in computer science classes.)<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">But wait, it gets worse:<span>&nbsp; <\/span><s>the code for Item() calls Count() also on each iteration to verify that the index is not out of bounds &ndash; that brings us up to a count of 1001000 MyLameObject references<\/s>.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><b>Edit<\/b>:<span>&nbsp; <\/span>As noted above, that isn&rsquo;t true for VB, though it would be for many other languages<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">And, of course, Item() itself needs to walk the list to actual get to the desired item, on every iteration &ndash; that adds 500500 more object hits (using the n(n\n+1)\/2 formula) , for a grand total of <s>1501500<\/s> 1500500 object hits. And all that just to concatenate 1000 strings!<span>&nbsp; <\/span>That, I fear, is going to slow down my code&rsquo;s performance somewhat.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">Now, of course I could add code to get track of values for Count(), and that would reduce my cost to a third of what it was.<span>&nbsp; <\/span>I could use some clever hashing algorithm to more easily get to the items while still being able to use method calls.<span>&nbsp; <\/span>I could enumerate the list myself instead of relying on &ldquo;Count&rdquo; or on &ldquo;Item,&rdquo; and that would really cut my costs down dramatically.<span>&nbsp; <\/span>Or, best of all, I could avoid reinventing the wheel and using the classes that VB.NET already supplies for me, since we do our best to optimize them.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">But that&rsquo;s not the point that I&rsquo;m trying to make here.<span><\/span><\/font><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>(Note: there was a grievous error in this post based on a bad assumption on my art regarding VB.&nbsp; Not feeling the need to hide my ignorance :-), I have instead made a number of edits in this post to bring it back to some semblance of reality.) One thing that gets me annoyed with [&hellip;]<\/p>\n","protected":false},"author":258,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[21,22,195],"tags":[101,165,166,167],"class_list":["post-1543","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-im-a-vb","category-matt-gertz","category-visual-basic","tag-matt-gertz","tag-vb2005","tag-vb2008","tag-vb2010"],"acf":[],"blog_post_summary":"<p>(Note: there was a grievous error in this post based on a bad assumption on my art regarding VB.&nbsp; Not feeling the need to hide my ignorance :-), I have instead made a number of edits in this post to bring it back to some semblance of reality.) One thing that gets me annoyed with [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/1543","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/258"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=1543"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/1543\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=1543"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=1543"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=1543"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}