{"id":50,"date":"2009-09-09T22:57:07","date_gmt":"2009-09-10T03:57:07","guid":{"rendered":"http:\/\/blog.bitsofgenius.com\/?p=50"},"modified":"2011-01-26T12:32:28","modified_gmt":"2011-01-26T16:32:28","slug":"the-lost-art-of-break-and-continue","status":"publish","type":"post","link":"https:\/\/blog.bitsofgenius.com\/?p=50","title":{"rendered":"The lost art of break and continue"},"content":{"rendered":"<p>BREAK and CONTINUE are two forms of loop control, which I have seen under-used lately.\u00a0 I think it is time to revisit how these two statements can help you make more maintainable and readable code, with some basic comments where needed.<\/p>\n<p>BREAK is used to prematurely exit a loop sequence, be it a WHILE loop, or a FOR loop.\u00a0 CONTINUE is used to force the next iteration of the loop.\u00a0 These two keywords exist verbatim in SQL and C\/C#\/Java, but all languages have them in some dialect.<\/p>\n<p>A great way to understand easier maintenance is the venerable CURSOR in SQL.\u00a0 Generally, a cursor loop is written as such:<\/p>\n<pre lang=\"sql\" line=\"1\">\r\nDECLARE @nValue1 INT, @nValueA INT, @nValue42 INT\r\n\r\nDECLARE curSingleRow CURSOR FOR SELECT Value1, ValueA, Value42 FROM Table\r\n\r\nOPEN curSingleRow\r\n\r\nFETCH NEXT FROM curSingleRow INTO @nValue1, @nValueA, @nValue42\r\nWHILE @@FETCH_STATUS = 0 BEGIN\r\n\r\n\/* ...\r\nprocess the single row here\r\n... *\/\r\n\r\n\/* ... get the next row to process ... *\/\r\nFETCH NEXT FROM curSingleRow INTO @nValue1, @nValueA, @nValue42\r\nEND\r\n\r\nCLOSE curSingleRow\r\nDEALLOCATE curSingleRow\r\n<\/pre>\n<p>This code is very familiar to SQL developers. The @@FETCH_STATUS value becomes non-zero if no further records are available, or some other error occurs.\u00a0 The problem with this code is that if a column in the select statement is added, dropped or changed, there are three points of maintenance: the declare statement, and two fetch statements.\u00a0 If the loop is rather large, the last fetch statement is going to be a long way down.<\/p>\n<p>Consider the following change to the code:<\/p>\n<pre lang=\"sql\" line=\"1\" escaped=\"true\">\r\nDECLARE @nValue1 INT, @nValueA INT, @nValue42 INT\r\n\r\nDECLARE curSingleRow CURSOR FOR SELECT Value1, ValueA, Value42 FROM Table\r\n\r\nOPEN curSingleRow\r\n\r\n\/* (1=1) means always true: intentional. Exit is forced within the loop itself *\/\r\nWHILE (1=1) BEGIN\r\n\r\n\/* ... get the first or next row to process ... *\/\r\nFETCH NEXT FROM curSingleRow INTO @nValue1, @nValueA, @nValue42\r\nIF @@FETCH_STATUS &lt;&gt; 0 BREAK\r\n\r\n\/* ...\r\nprocess the single row here\r\n... *\/\r\n\r\nEND\r\n\r\nCLOSE curSingleRow\r\nDEALLOCATE curSingleRow\r\n<\/pre>\n<p>The change makes the WHILE loop appear infinite, but it simply guarantees that the execution will always enter the loop.\u00a0 Notice that I explicitly put a comment there to ensure that anyone maintaining the code understands the intent.\u00a0 Since the FETCH statement is identical for the first and successive records, that is what will occur with the same statement&#8211;on the initial entry and upon successive iterations.\u00a0 The IF statement checks for either no more records or an error condition, and will trigger the BREAK statement when that happens.\u00a0 Otherwise, the code below the IF statement continues to execute, and will iterate back to the WHILE statement.\u00a0 This scenario also covers the case of no rows returned by the SELECT statement.\u00a0 The BREAK statement immediately exits the WHILE loop, executing the CLOSE statement.<\/p>\n<p>This now reduces maintenance to a DECLARE statement and a single  FETCH statement.\u00a0 To me, the code is also more readable.\u00a0 My first instinct reading the original code is to question why the FETCH statement was repeated in the original code (it&#8217;s just because of the way my brain works).<\/p>\n<p>BREAK and CONTINUE are extremely useful for creating short-circuiting logic, within a main logic condition.\u00a0 Example: Say you needed to parse a set of command arguments, where certain argument combinations would cause remaining arguments to be ignored, or cause the single argument to be ignored.\u00a0 The code could be written like <a href=\"\/CodeView\/BreakAndContinueDemo_Console_cs.html\" target=\"_blank\">this<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>BREAK and CONTINUE are two forms of loop control, which I have seen under-used lately.\u00a0 I think it is time to revisit how these two statements can help you make more maintainable and readable code, with some basic comments where needed. BREAK is used to prematurely exit a loop sequence, be it a WHILE loop, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,18,13,17,1],"tags":[],"class_list":["post-50","post","type-post","status-publish","format-standard","hentry","category-dotnettechniques","category-sql-server","category-technologythoughts","category-tips-and-tricks","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/50","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=50"}],"version-history":[{"count":3,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions"}],"predecessor-version":[{"id":244,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions\/244"}],"wp:attachment":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=50"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=50"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}