Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspxHere's an interesting question I got the other day:
We are writing code to translate old mainframe business report generation code written in a BASIC-like language to C#. The original language allows "goto" branching from outside of a loop to theen-USTelligent Evolution Platform Developer Build (Build: 5.6.50428.7875)re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9591148Wed, 06 May 2009 15:55:03 GMT91d46819-8472-40ad-a661-2c78acb4018c:9591148Itai<P>For the love of god!!</P>
<P>Why would you do a direct translation of the code? Just use a loop and some if conditions in it to skip sections.</P>
<P>DO NOT USE GOTO!<BR></P>
<DIV class=yellowbox>
<P>Why? Well, suppose you have a million lines of code to translate. Your choices are (1) spend 10 hours writing a literal translator that generates ugly code, (2) spend 10 hours writing a literal translator and then 90 hours rewriting all the code that involves gotos, or (3) spend 10000 hours rewriting the whole system from scratch. The costs of those three choices are $1000, $10000 and $1000000, respectively. Suppose you have to pay for it. Which would you choose? How much are you willing to spend on beautifying code that already works just fine? -- Eric</P></DIV>
<P>&nbsp;</P><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9591148" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9581723Fri, 01 May 2009 05:25:52 GMT91d46819-8472-40ad-a661-2c78acb4018c:9581723Clyde Coulter<p>How much knowlege is available about how the original program works, or (more importantly) what it is supposed to be doing?</p>
<p>A lot of old code can be reduced (in lines of codes) by 20 to 80%, purely on the basis that much of it was cut/pasted from other code that did the same thing on a different instance of data. &nbsp;This is why classes/objects/interfaces/etc came about to begin with.</p>
<p>I agree it is painful to take in hand thousands of lines of code and re-design and re-write it, but it many cases it is well worth it, and would take a lot less time than one might think (there is a certain moment of inertia that begins to build once you get familiar with a coding style no matter how ugly it might seem).</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9581723" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9578079Thu, 30 Apr 2009 06:24:07 GMT91d46819-8472-40ad-a661-2c78acb4018c:9578079Gene Naden<p>Reading most of this thread, I was amazed to discover how interesting it is to look at GOTO from 20 or 30 different points of view.</p>
<p>Getting back to the question that started this thread: the reason she/he wants to convert the old BASIC code to C# is (presumably) so that it will use the .NET CLR and interoperate with other .NET code. The problem is a kind of &quot;impedance mismatch&quot; meaning that BASIC is so dumb, and C# is so smart, that conversion is impractical. What we need is a cruder version of C# (call it &quot;C-dumb&quot;) that is closer to the BASIC code. Has anyone considered FORTRAN?</p>
<p>Seriously, I once had to write a state machine once to handle Asterisk telephone events and it was a heck of a lot easier to write, read and modify using a few GOTOs versus keeping it &quot;pure&quot; with strange WHILEs.</p>
<p>The argument that MSIL uses GOTO so we should use them too is suspect. Consider writing a specification for a steel screw. Yes, it is made of molecules but when you order a certain screw do you really want to describe how all the molecules relate to one another? It is the wrong level of abstraction.</p>
<p>Maybe God Almighty will write the answer with fiery letters in the sky: &quot;GOTO IS/IS NOT HARMFUL!&quot;</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9578079" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9554167Fri, 17 Apr 2009 15:26:54 GMT91d46819-8472-40ad-a661-2c78acb4018c:9554167Kevin<p>Bad code is bad code. One needs to understand what branching into a FOR statement in their compiler means. I have used languages where there is only the goto. &nbsp;I have also see bad FOR statements.</p>
<p>10 FOR i = 1 TO 10</p>
<p>20 &nbsp; &nbsp; PRINT i</p>
<p>30 NEXT i</p>
<p>40 LET i = i * 2</p>
<p>50 PRINT i</p>
<p>What is the value of i? 20 or 22. &nbsp;This depends on the BASIC version.</p>
<p>Of course we should not use i outside to loop.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9554167" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9553332Thu, 16 Apr 2009 21:45:50 GMT91d46819-8472-40ad-a661-2c78acb4018c:9553332Bryan<p>One time long ago I inherited a program written in C-tran. &nbsp;The author knew and thought in FORTRAN but had to code the app in C, and a veritable mess of code resulted that contained over 400 GO TO stetements. &nbsp; We stumbled along maintiaing it, never given the time to rewrite what was &quot;working&quot; but always allowed the time to analyze the mess of spaghetti for unintended consequences of the changes we were planning to make (and deal with the ones we did not foresee). </p>
<p>We recruited a bright guy from the customer support team to come into the product development team and his soel condition for accepting the position was they he be allowed to rewrite that app. &nbsp;It was accepted and the final product after3 months was easier to understand, easier to maintain and easier to extend. </p>
<p>GOTO is just a tool - but it is VERY dangerous in the hands of those who do not fear it.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9553332" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9552315Thu, 16 Apr 2009 09:33:39 GMT91d46819-8472-40ad-a661-2c78acb4018c:9552315Farrukh<p>this is funny stuff.</p>
<p>We are being guided to the old, frustrating, spider webs of looping with GOTOs. </p>
<p>this shouldnt practically be an approach in professional development using C#.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9552315" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9536602Tue, 07 Apr 2009 23:33:18 GMT91d46819-8472-40ad-a661-2c78acb4018c:9536602Charles Young<p>Turns out that a simple loop to iterate through a safe array can be a bit faster than my version of Duff's Device in .NET. &nbsp; A loop to iterate through allocated stack space (using stackalloc) using an unsafe pointer is much faster. &nbsp; So, 'Duff's device' in C# is sub-optimal. &nbsp; A case of hand-rolled de-optimization! &nbsp; Full marks to C# for being so expressive, but don't use the technique!</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9536602" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9536414Tue, 07 Apr 2009 21:19:12 GMT91d46819-8472-40ad-a661-2c78acb4018c:9536414Brian Smith<p>re: Duff's Device... Hand-rolled optimization in C#? You guys are funny.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9536414" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9534885Tue, 07 Apr 2009 04:17:25 GMT91d46819-8472-40ad-a661-2c78acb4018c:9534885Charles Young<p>With regard to Duff's device (see comments from A.C.Hynes and Matthew Whited above) here is another C# version which is closer to the original. &nbsp; C# is surprisingly expressive at times:</p>
<p>namespace DuffsDevice</p>
<p>{</p>
<p> &nbsp; &nbsp;using System;</p>
<p> &nbsp; &nbsp;class Program</p>
<p> &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;static void Main(string[] args)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unsafe</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;short[] data = new short[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;short register = -1;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fixed (short* dataPtr = &amp;data[0])</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DuffsDevice(&amp;register, dataPtr, data.Length);</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(register);</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;}</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &lt;summary&gt;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// C# approximation to Duff's device.</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// </p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// void send(register short *to, register short *from, register int count)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// {</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; register int n=(count+7)/8;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; switch(count%8)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; {</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 0: do{ *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 7: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 6: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 5: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 4: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 3: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 2: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; case 1: &nbsp; &nbsp; *to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; &nbsp; &nbsp; }while(--n&gt;0);</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &nbsp; &nbsp; }</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// }</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &lt;/summary&gt;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &lt;param name=&quot;to&quot;&gt;&lt;/param&gt;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;/// &lt;param name=&quot;from&quot;&gt;&lt;/param&gt;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;unsafe static void DuffsDevice(short* to, short* from, int count)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int n = (count + 7) / 8;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;switch (count % 8)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 0:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 7;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 7:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 6;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 6:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 5;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 5:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 4;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 4:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 3;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 3:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 2;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 2:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;goto case 1;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case 1:</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*to = *from++;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (--n &gt; 0) goto case 0; else break;</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;}</p>
<p> &nbsp; &nbsp;}</p>
<p>}</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9534885" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9534153Mon, 06 Apr 2009 21:07:43 GMT91d46819-8472-40ad-a661-2c78acb4018c:9534153Samuel Warren<p>Seriously, we have methods now...... If you need to jump to something inside a loop, then it should probably be in a separate method.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9534153" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9528934Thu, 02 Apr 2009 13:26:29 GMT91d46819-8472-40ad-a661-2c78acb4018c:9528934madkat<p>Eric:</p>
<p>If you have 500,000 lines of working code which is riddled with GOTO statements, and you then replicate it on a line-by-line (or fragment-by-fragment if you prefer) basis, there's no guarantee that it's going to work in the target environment. There are other factors such as that pointed out by bmann: The value of J upon exit may be different, which means the code could fail catastrophically at its first run, or even at some later point when FOO eventually does equal True, and then you'd be left with the serious headache of having to debug it. If you untangled it properly, it would make that debugging much more simple and the code would be readable to anyone else who came to look at it.</p>
<p>Aside from that, if it's working, why would you move it to another language?</p>
<p>bmann: Good point... but with our new refactored code we should be able to see exactly where the problem is and what the problem is at aa glance :)</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9528934" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9523139Tue, 31 Mar 2009 19:17:53 GMT91d46819-8472-40ad-a661-2c78acb4018c:9523139Nick<p>if (StatusOK) {</p>
<p> &nbsp; if (DataAvailable) {</p>
<p> &nbsp; &nbsp; &nbsp;ImportantVariable = x;</p>
<p> &nbsp; &nbsp; &nbsp;goto MID_LOOP;</p>
<p> &nbsp; }</p>
<p>} else {</p>
<p> &nbsp; ImportantVariable = GetSomeValue();</p>
<p> &nbsp; MID_LOOP:</p>
<p> &nbsp; //Lots of code</p>
<p>}</p>
<p>I'm disappointed that no-one has mentioned Steve McConnell yet.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9523139" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9521996Tue, 31 Mar 2009 11:45:53 GMT91d46819-8472-40ad-a661-2c78acb4018c:9521996bmann<p>Your point about the difficulty in understanding convoluted code is well taken. &nbsp;In fact some of the coded solutions produced wrong results. &nbsp;In the case where FOO is true they fail to start and end the list with &quot;---&quot;.</p>
<p>Actually, your example and solution point out the fundamental translation problem and solution. &nbsp;Antique BASIC treated for a FOR loop index as a global variable and the loop condition was checked in the NEXT statement (Always on iteration was executed). &nbsp;The best way to handle the translation problem is to break the FOR loops into initialization, Value adjustment, and conditional jumps, much like you did ( I would check end conditions at the NEXT statement ).</p>
<p>There are also wonderful dialect specific factors like what is the value of j after the loop? &nbsp;Is it 10 or 11? &nbsp;That would depend on the specific implementation and is unfortunately something that may matter for the code that followed. &nbsp;After all it was often possible to jump out of FOR loops before termination.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9521996" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9515980Sat, 28 Mar 2009 16:54:01 GMT91d46819-8472-40ad-a661-2c78acb4018c:9515980madkat<p>(with a lower case j in line 3, obviously)</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9515980" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9515978Sat, 28 Mar 2009 16:52:57 GMT91d46819-8472-40ad-a661-2c78acb4018c:9515978madkat<P>What I was trying to say is that the code should be refactored properly. Using Goto is ugly and difficult to read. Simply check what the code is trying to achieve and find the best way to replicate that functionality. </P>
<DIV class=yellowbox>
<P>Which you will note was my first suggestion, yes. But what if you have&nbsp;five hundred thousand lines of goto-ridden&nbsp;mainframe code to&nbsp;translate? "Ugly and difficult to read" is better than "not working", and cheaper&nbsp;and more accurate than "translate five hundred thousand lines of code by hand". -- Eric</P></DIV>
<P>Just because the original code uses a Goto, that doesn't mean our new code has to use any at all. We could similarly do this:</P>
<P>int j = FOO ? 3 : 1;<BR>while (j&lt;=10)<BR>&nbsp; PRINT (string.Format("{0}\r\n---",J++));<BR>PRINT ("Done");</P>
<DIV class=yellowbox>
<P>Using your human intelligence to&nbsp;create a goto-free program that matches the semantics of one particular code&nbsp;fragment is easy. Writing a program that does that to any arbitrary fragment&nbsp;is rather more difficult, I assure you. -- Eric</P></DIV><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9515978" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9515795Sat, 28 Mar 2009 13:04:32 GMT91d46819-8472-40ad-a661-2c78acb4018c:9515795Hugh<p> &nbsp; &nbsp; for(J = FOO ? 3 : 1; J &lt;= 10; J++) </p>
<p> &nbsp; &nbsp; &nbsp; PRINT (string.Format(&quot;{0}\r\n---&quot;,J));</p>
<p> &nbsp; &nbsp; PRINT (&quot;Done&quot;); </p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9515795" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9513705Fri, 27 Mar 2009 12:50:47 GMT91d46819-8472-40ad-a661-2c78acb4018c:9513705richard develyn<p>I think people are confusing GOTO with branching.</p>
<p>GOTO is a programming statement which allows unstructured branching. Other programming statements (if-then, for, while, throw) only allow branching within a particular context or programming structure. Unstructured branching allows you to write incomprehensible code *very* easily. For example (using pseudo-basic)</p>
<p>10 x = 110</p>
<p>20 if ( x is even ) goto 40</p>
<p>30 x = 3 * x + 1</p>
<p>40 x = x / 2</p>
<p>50 if ( x &gt; 10 ) goto 20</p>
<p>60 print x</p>
<p>I mean, never mind what x might be at the end, can we even be sure this will finish for different start values of x?</p>
<p>(Please don't get caught up on this being a mathematical example, BTW. Statements 20 to 50 could be totally non maths related - as long as they interfere with each other you are going to get a problem).</p>
<p>It's very easy with unstructured branching to start getting this sort of effect. Of course, you could use GOTO to duplicate structured branching (like duplicating a while loop), but why do it? It is far nicer when you come to look at your code to know there are *no* GOTOs in it rather than have to analyse whether each individual GOTO is sensible or not.</p>
<p>As to the oft quoted example of error handling in a sequence of method calls, I believe this indicates bad design. First of all I think you need to carefully consider what *is* an error, then isolate your error handling in one group of methods or classes or whatever, so that the rest of your code isn't burdened with constantly having to check whether things are happening ok. i.e., it is better to write:</p>
<p>method_a()</p>
<p>{</p>
<p>method_a_1();</p>
<p>method_a_2();</p>
<p>etc</p>
<p>}</p>
<p> - than:</p>
<p>method_a()</p>
<p>{</p>
<p>if ( method_a_1() == ok )</p>
<p>{</p>
<p>if ( method_a_2() == ok )</p>
<p>{</p>
<p>etc</p>
<p>}}}}}}}}}}}}}}}.</p>
<p> - or some equivalent using gotos.</p>
<p>Where you simply are unable to pre-check for an error (like that nuclear refinery you were monitoring has just gone off-line), you should probably use an excepion and exit (gracefully) until somebody fixes the problem.</p>
<p>Richard</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9513705" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9510291Thu, 26 Mar 2009 12:54:38 GMT91d46819-8472-40ad-a661-2c78acb4018c:9510291Peter Wone<p>GOTO is all about sequence in the context of state. Code in this form is inimical to parallelisation. </p>
<p>This is easy to automate with functional programming languages, where dependencies on evaluation sequence are necessarily explicit. It is damn near impossible to automate in procedural languages where many dependencies are not only implicit but often indirectly implicit (due to side effects).</p>
<p>When a language requires explicit declaration of dependencies, laziness inhibits their spurious creation. Better quality code results, and it is incidentally more amenable to optimisation for multiple CPUs.</p>
<p>As in life, time is the great enemy. </p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9510291" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9504284Tue, 24 Mar 2009 17:10:51 GMT91d46819-8472-40ad-a661-2c78acb4018c:9504284David W<p>I don't think anyone here fails to realize that all flow-of-control structures end up as GOTO's at a machine level. The point is that the machine can manage the GOTO's, but for humans its like reading a story, telling someone to jump two pages ahead, then jump three pages back. Yeah, you can do it, but geez, does that make it a good idea? Heavens - the computer can count to a zillion in binary, but that doesn't mean its a good idea for human consumption.</p>
<p>That aside, my personal beef isn't with &quot;goto's&quot; per se, but when they are being used in obviously lazy situations when just a few minutes' effort would have created a more streamlined control flow structure. In *most* cases, a GOTO is a hack, an amputation of logic where a few stitches of design and discretion would have avoided an ugly and usually unnecessary scar. I've rarely seen a structure made *more* elegant with a blunt GOTO. But that's just me...</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9504284" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9500740Mon, 23 Mar 2009 11:09:06 GMT91d46819-8472-40ad-a661-2c78acb4018c:9500740Jevgenij Volosatov<p>This code</p>
<p>10 &nbsp; J = 2</p>
<p>20 &nbsp; IF FOO THEN GOTO 50</p>
<p>30 &nbsp; FOR J = 1 TO 10</p>
<p>40 &nbsp; &nbsp; PRINT J</p>
<p>50 &nbsp; &nbsp; PRINT &quot;---&quot;</p>
<p>60 &nbsp; NEXT</p>
<p>70 &nbsp; PRINT &quot;DONE&quot;</p>
<p>can write on C# using new bool variable:</p>
<p>j = 2;</p>
<p>bool foo1 = foo;</p>
<p>if (!foo) </p>
<p> &nbsp; &nbsp;j = 1;</p>
<p>for (; j &lt;= 10; j ++)</p>
<p>{</p>
<p> &nbsp; &nbsp;if (!foo1)</p>
<p> &nbsp; &nbsp; &nbsp; &nbsp;print (j);</p>
<p> &nbsp; &nbsp;foo1 = false;</p>
<p> &nbsp; &nbsp;print (&quot;---&quot;);</p>
<p>}</p>
<p>print (&quot;DONE&quot;);</p>
<p>Any code do not repeates twice!</p>
<p>You can use foo instead foo1, when this variable do not required in other code part.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9500740" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9496326Sat, 21 Mar 2009 22:45:36 GMT91d46819-8472-40ad-a661-2c78acb4018c:9496326Gabe<p>I would suggest converting the code to MSIL, then decompiling the MSIL into C#. That way you get C# code, but it will still have loops where ever possible.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9496326" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9493741Sat, 21 Mar 2009 01:18:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:9493741Vitaly<p>What would people say at goto's funeral?</p>
<p>goto's wife: &quot;Oh my sweet goto, I can't loop without you&quot;</p>
<p>goto's kids: &quot;we want our goto back&quot;</p>
<p>goto's 3rd cousins' brother in-laws' 5th pets' owner: &quot;He was pure evil, evil I tell you!&quot;</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9493741" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9492929Fri, 20 Mar 2009 20:27:52 GMT91d46819-8472-40ad-a661-2c78acb4018c:9492929StreetUrchin<p>Nothing like stepping on a setjmp / longjump landmine. I've seen some pretty clever exception-like handling built around this construct using C/C++. It drove me nuts till I figured it out. Another developer had called setjmp from main, then whenever his deep library code encountered an error he'd call longjump. The longjump would set the instruction pointer back to the beginning of the program.</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9492929" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9492556Fri, 20 Mar 2009 17:48:05 GMT91d46819-8472-40ad-a661-2c78acb4018c:9492556Gert-Jan van der Kamp<p>I meant flowchart from Visio to be precise. </p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9492556" width="1" height="1">re: Loops are gotoshttp://blogs.msdn.com/b/ericlippert/archive/2009/03/10/loops-are-gotos.aspx#9492533Fri, 20 Mar 2009 17:37:56 GMT91d46819-8472-40ad-a661-2c78acb4018c:9492533Lee<p>&gt; The IL itself does allow it so why not the compiler. Let the programmer be the judge to use it or not.</p>
<p>Because the compiler must enforce a semantic level of meaning on the code so that it can effectively generate IL code that does what you wrote in the higher level language.</p>
<p>Consider the difference between for loops and if-else statements. There is quite a bit of difference in the amount of setup required to make each work.</p>
<p>if-else: No setup required, beyond performing the test condition and branching to the else part. Since there's no setup, it's no problem to goto into either the if-body or else-body.</p>
<p>for loop: At minimum, initializing the loop index and check that it meets the test condition. (foreach is even worse... find the appropriate enumerator, get that all setup, etc., etc...) With all this setup, how do you reasonably do a goto into the body of a for loop AND get provably correct code for EVERY case? Not too likely. (On the other hand, you can goto out of a for loop, because that amounts to little more than a break.)</p>
<div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=9492533" width="1" height="1">