Visual Basic .NET/Logic Control Structures
While Visual Basic is far from the point where one could create an effective AI that can make rational independent decisions, it does have a number of logic control structures that allow it to choose what to do, and how many times. In this lesson, we will take a look at these structures and how they are used.
Introduction[edit | edit source]
Logic control structures allow the execution to jump some code, execute some code a certain number of times, or operate on collections of objects or data. Without this ability software would be pretty useless since it would still take a lot of time to write the code, but then the user would have to make all of the decisions, sometimes hundreds or thousands of times. No one would use it.
Before we start talking about these structures, however, lets take a look at collections as they play a part in this lesson.
Collections[edit | edit source]
A collection is a structure that allows objects of a specified type be grouped so that they can have code run against them much more easily. Let us take for instance the Controls collection in the Form class. If you take a look at the previous lessons project, type inside a Sub block the following:
After typing the last period intellisense pops up a list of the applicable properties and methods that can be run against that collection. To access a single object in that collection, you can use one of several methods. You can use the items index, that is the number that describes it's position in the collection; this is usually indicative of the order in which the items where added to the collection. You can also use the key; this depends on the collection and the items that make it up. The key is a unique value in the objects that are stored in the collection. Sometimes the key is the name of the object, sometimes (rarely) it is the caption or text of the object, sometimes it is an arbitrary ID number. The last method we will go over in a few minutes. For now, just know that typically, a collection contains a single type of object (or datatype) and has built-in methods for working with those types.
Logic Control[edit | edit source]
If...Then[edit | edit source]
This is probably the simplest logic control structure. It tests one or more expressions and if they are true, then it executes the code within the structure. Let's take a look.
If MyForm.Name = "Hello_World" Then MyForm.Text = "Hello World" End If
The above code tests a single condition (Is the Form Named "Hello_World"?). If it is, then set the Form Text (the titlebar) to say "Hello World". If not, don't do anything, skip to after the End If and continue execution. This same statement can be written "inline" lik so.
If MyForm.Name = "Hello_World" Then MyForm.Text = "Hello World"
Since the above line has the condition and code to execute on the same line, there is no need for an End If. If you have multiple items to test and a simple line of code to execute, it makes it worthwhile to do inline. It is much easier to line them all up thatn to wander in and out of If blocks. But what if you want to execute some other code if the statement is false?
Select Case e.KeyCode Case Keys.Left Pos.X -= 2 Dir = "left" Case Keys.Up Pos.Y -= 2 Dir = "up" Case Keys.Right Pos.X += 2 Dir = "right" Case Keys.Down � Pos.Y += 2 Dir = "down" Case Keys.Space 'this is where i cant figure out 'what to use for the jump animation 'to actually make the sprite jump End Select
If...Else...Then[edit | edit source]
If MyForm.Name = "llo_World" Then MyForm.Text = "Hello World" Else MyForm.Text = "Goodbye Cruel World" End If
This block allows you to test an expression, and if true, then it will execute some code, but if untrue (whatever the other value of MyForm.Name) then execute this second set of code. This is useful if you afdfgdfre looking for only a single value or result from something, and everything else is evaluated otherwise.
If...ElseIf...Then[edit | edit source]
If MyForm.Name = "Hello_World" Then MyForm.Text = "Hello World" ElseIf MyForm.Name = "Goodbye_Cruel_World" MyForm.Text = "Goodbye Cruel World" End If
The above is likely self explanatory. You test one expression, if that is true, fine, execute some code. If false, test another expression, if true fine, if not move on. ElseIf can be used any number of times. It can also be used with regular Else. In cases like that, if all If(s) and ElseIf(s) are evaluated False, then the code in Else will be executed, otherwise execution of the statement in the If/ElseIf block will execute.
If MyForm.Name = "Hello_World" Then MyForm.Text = "Hello World" ElseIf MyForm.Name = "Goodbye_Cruel_World" MyForm.Text = "Goodbye Cruel World" ElseIf MyForm.Name = "Mahalo" MyForm.Text = "Thanks for all the fish" Else MyForm.Text = "I have no idea who I am" End If
Select Case[edit | edit source]
You can use ElseIf to evaluate a single property amongst many different possible values, but it is kind of ugly and takes up a lot of space, not to mention repetitious. Enter Select Case. Select Case allows evaluation of a single item and checks the value against many possibilities.
Select Case Me.Name Case "Hello_World" Me.Text = "Hello" Case "Goodbye" Me.Text = "Goodbye cruel world" Case "Mahalo" Me.Text = "Thanks for all the fish" Case "Google_Earth" Me.Text = "I can see my house" Case "Trebuchet" Me.Text = "Fire for effect!" Case Else Me.Text = "I still have no idea who I am" End Select
Start with the Select Case keywords, then the property you wish to evaluate. Then followup with case statements and every value that is of interest. Under each case statement, put the code that you want executed. If there are any other possible values of the property or function, and you want something to happen in that case, the Case Else can take care of that eventuality.
For X[edit | edit source]
So what if you want to execute some code a specific number of times? There are a few times when this happens. Say we have a sort of calculator that computes the maximum number that an X-digit binary number can be. Well we might have something like so.
Dim decMyValue As Decimal = 1 'These two variables are for Dim intMyInput As SByte = CSByte(Me.txtMyText.Text) 'counting and multiplying Select Case intMyInput 'Evaluate intMyInput Case Is < 96 'if it is less than 96 For i As SByte = 0 To (intMyInput - 1) 'Do the following a X times decMyValue = decMyValue * 2 'Multiply the number by 2 Next 'Loop and do it again Case 96 'if it is equal to 96 Me.txtMyText.Text = "79228162514264337593543950334" 'Set the textbox text to this Exit Sub 'and stop execution Case Else 'if it is anything else decMyValue = 0 'Set decMyValue to 0 MsgBox("Please enter a number between 1 and 95") 'Display a message box End Select 'Stop evaluating intMyInput Me.txtMyText.Text = (decMyValue - 1) 'Set the textbox text to the value
I realize this is a bit sudden, but this will let me explain some things, and it will give a good example of how you could use a couple of these structures. First, we have two variable declarations:
Dim decMyValue As Decimal = 1 Dim intMyInput As SByte = CSByte(Me.txtMyText.Text)
In case you want to know, CSByte is a function that converts or coerces a value from one type to another. In this case it is trying to convert the text in the textbox into an SByte value. The other variable will handle the computed value. Next we have a Select Case statement with a For loop Nested inside it. You can nest these structures inside one another to achieve some pretty amazing and sometimes convoluted logic.
Select Case intMyInput
So evaluate the variable intMyInput.
Case Is < 96
If the value is less than 96 then do the following.
For i As SByte = 0 To (intMyInput - 1)
Start a loop that is executed a certain number of times (in this case it is equal to the intMyInput value).
decMyValue = decMyValue * 2
Mutiply the value times 2 then reassign it to the variable.
Then loop around and do it again.
Case 96 Me.txtMyText.Text = "79228162514264337593543950334" Exit Sub
If intmyinput is 96, then set txtMyText,Text to this value. Then stop execution.
Case Else decMyValue = 0 MsgBox("Please enter a number between 1 and 95")
Otherwise popup an error message and let the user try again.
The Exit Sub statement above allows you to stop execution if something occurs. In this case, the decimal variable could not hold that huge number, so I just assigned the number (as a string) to the textbox.Text property, and stoped execution early since the decMyValue variable was not populated with anything except 1. If I had not done this, the line at the bottom would have returned 0 to the Textbox.
For Each[edit | edit source]
Remember the bit about collections earlier? What if you wanted to inspect or alter everything in a collection (or both)? For Each... is the answer. For Each allows you to iterate through a collection from the first object to the last (in that order) doing or checking something in each object.
Lets say for instance that we have a form with a number of textbox controls. We want to check to see if any of them have anything in them. If one does, then do something like make their backgrounds green.
Public Sub CheckTextboxes() For Each MyTextBox As Control In Me.Controls 'Look at all of the items in Me.Controls If TypeOf (MyTextBox) Is TextBox Then 'If the current item is a textbox If MyTextBox.Text <> "" Then 'And if the Textbox has text MyTextBox.BackColor = Color.LightGreen 'Set the background color to 'light green End If End If Next 'Loop to next item End Sub
This can be very powerful if you wish to affect a large number of objects or a certain subset of objects out of a large set.
Do While/Do Until[edit | edit source]
These two structures are similar to For except instead of just iterating up to a certain number of times, it continues to loop until a certain event occurs or an item reaches a specific value. The big difference between the two is in when they execute/stop executing.
Dim MyVal as Sbyte = CSbyte(Me.txtMyTextBox.Text) Do While MyVal > 100 MsgBox("The value is " & MyVal) MyVal -= 2 Loop
Do While will execute as long as MyVal is greater than 100.
Dim MyVal as Sbyte = CSbyte(Me.txtMyTextBox.Text) Do Until MyVal > 100 MsgBox("The value is " & MyVal) MyVal -= 2 Loop
Do Until will execute as long as MyVal is less than 100. (given that Myval is contiually subtracted in this example, it will never be over 100 unless it starts there.)
Try..Catch[edit | edit source]
The last structure is not a looper or value checker. It catches exceptions. If you have some code that expects a value or some event to have happened, you have to assume that there is some chance that the value will be invalid somehow or that the event will be missed. Try...Catch executes some code, then if there is an error, executes something else.
For example, if we have a textbox that we are specifying a number value and we want that value multiplied several times. We only want it to go up to 128 so we use an SByte data type. But what if the value entered causes th multiplication to spit out a number higher than what the SByte can hold?
If you executed the folowing code, any value above 5 would cause the execution to halt and the program will crash.
Myval *= 22
However with this block, you can catch the exception, provide some helpful advice, and continue running.
Try Myval *= 22 Catch ex As Exception MsgBox("Value too high. Try something lower.") End Try
Code Block Scope[edit | edit source]
One item of note: any variables that are dimensioned inside a code block like the ones above, will only be useable in that code block. As soon as execution exits the code block, the variable is removed, and the memory is freed. If you want the variable to be useable outside the block, dimension it before the start of the block.