Code Focused

Tricks with Goto in Visual Basic and C#

Goto statements, whether they're used in Visual Basic or C#, can be confounding as to their purpose in some contexts.

The Goto statement in both Visual Basic and C# seems like an amazing tool for getting out of sticky code blocks. But it can also get you into sticky blocks, at least in Visual Basic. Consider this somewhat useless block of Visual Basic code:

Dim pass As Integer = 0
If (True) Then
  Dim passFactor As Integer = 5
ShowMessage:
  pass += 1
  MessageBox.Show($"Pass value = {pass * passFactor}")
End If
If (pass = 1) Then GoTo ShowMessage
MessageBox.Show("Finished")

This code will show three message boxes, the first two with pass values of 5 and 10, respectively, and then the "Finished" message. The GoTo statement returns back to the inner conditional block for a second chance at the message display, albeit with an updated pass value. But the results are somewhat different if you start out with a jump directly to the message portion of the code:

Dim pass As Integer = 0
GoTo ShowMessage ' <-- This is new!!!
If (True) Then
  Dim passFactor As Integer = 5
ShowMessage:
  pass += 1
  MessageBox.Show($"Pass value = {pass * passFactor}")
End If
If (pass = 1) Then GoTo ShowMessage
MessageBox.Show("Finished")

The updated code still shows three messages, but the first two messages display the text, "Pass value = 0," instead of the "5" and "10" versions of the original code. This change occurs because the GoTo statement jumps over the initialization of the passFactor variable, causing it to retain its default zero setting.

Keep in mind that although the GoTo statement jumped over the initialization of the passFactor variable, it didn't jump over the instantiation of that same variable. In Visual Basic, all local variables, even those scoped within a block (such as an If statement block) are created when the method begins and, therefore, have lifetimes that endure for the full duration of the method.

Although you cannot write code to access the passFactor variable outside of its containing If block, it still exists outside of that block, because it was brought into being outside of that block, as a part of the method's initialization process. This has the side effect of giving Visual Basic a lot of flexibility with its GoTo statements. Making a random jump into the middle of an If block is safe; you can access inner-scoped variables in that block, even if it appears that the GoTo statement bypassed the declaration of those scoped variables, like passFactor.

C# isn't so benevolent with its goto jumps. The equivalent and equally useless sample code, when converted to C#, will not compile:

int pass = 0;
if (true)
{
  int passFactor = 5;
ShowMessage:
  pass += 1;
  MessageBox.Show($"Pass value = {pass * passFactor}");
}
if (pass == 1)
  goto ShowMessage;
MessageBox.Show("Finished");

The error occurs with the goto statement. From its perspective, the ShowMessage label doesn't exist, because it appears in a different scope context. This restriction is necessary, in part, because of the way C# treats locally scoped variables.

While Visual Basic instantiates all local variables when a method first begins, C# instantiates inner-scoped variables (like passFactor) only when that inner scope is accessed by the code. In this case, jumping into the middle of the if block, especially after the passFactor declaration line, could enable access to uninitialized and even undeclared variables. To prevent such dangers, C# locks down goto jumps between certain scope contexts.

The solution, of course, is to restructure the code so that the cross-scope jump becomes unnecessary. Or to write code that does something useful. That would also be a solution.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.

comments powered by Disqus

Featured

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events