VbLessons
Teaching VB.NET, the right way.
Navigation ☰
Creating A New Project
Creating a new project will depend entirely on your developing environment. The type of project used throughout the lessons is a Console Application.
A Console Application uses a command-line and is sometimes referred to as a text-only interface.
Sandbox Environment
If you decide to use a Sandbox like dotnetfiddle, then follow these instructions:
- Create a new fiddle
- Optionally change the target language to VB.NET
- Optionally change the project type to console
The screenshot above is of dotnetfiddle. Not every sandbox is the same, but they do have similarities. In dotnetfiddle, the code goes in the main text editor and any input/output from the console goes text editor at the bottom of the page.
Visual Studio
If you decided to use Visual Studio, then follow these instructions:
- Create a new project using either:
- The shortcut key Ctrl + Shift + n.
- Selecting File > New > Project from the menu.
- Optionally change the language to Visual Basic.
- Optionally change the platform to Windows.
- Optionally change the project type to Console.
- Select Console Application (.NET Framework).
- Click on the Next button.
- Optionally configure your project by changing the project's name, location, etc.
- Click on the Create button.
The screenshot above is of Visual Studio 2019 Community Edition. The code goes in the main text editor and when you click on Start (shortcut key: F5) it runs the command line.
New Project
Go ahead and create a new project. There should be some automatically generated code that looks something to the effect of the following:
Imports System
Public Module Module1
Public Sub Main()
End Sub
End Module
The first line imports the System namespace to be used throughout the code. Namespaces can be thought of as libraries that hold existing code.
The second line creates a new module named Module1. Modules can be thought of as a generic code container.
The third line creates a new method named Main. We will discuss methods later on, but for now understand that when the Console Application runs it knows to start running the code inside of the Main method.
This is the basic project structure that will be used throughout the lessons.
Option Strict
Description
Before we dive into programming, I would like to take a moment to discuss an optional configuration in VB.NET called Option Strict. You can find the documentation here: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/option-strict-statement
Option Strict is a powerful feature in VB.NET that enforces stricter type checking by the compiler. When enabled, it requires explicit conversions between different data types. I highly encourage you to enable Option Strict as it will ensure that you write high-quality code and greatly reduce the likelihood of unexpected errors.
There are several ways to turn Option Strict on:
- Via code
- Via project properties (Visual Studio only)
- Via IDE options (Visual Studio only)
Personal Note
Look, I know that I'm throwing out some technical jargin at you and I'm sorry. It's just that, in my opinion, Microsoft made a very poor decision to have Option Strict turned off by default.
At the end of the day you really should turn Option Strict on. You will be a better developer, make less mistakes, and your code will run more efficiently.
Via Code
To turn Option Strict on via code, type the following line at the very top of your code file. This goes above any code at all, including any code that was automatically generated:
Option Strict On
This works well for individual code files, but what happens if you have 50 million files? Do you really want to add that every single time?
Very rarely should Option Strict be turned off, typically what I will do is enable it either through properties or through the IDE options. Then in those rare cases where I need to turn it off, I will turn it off for individual code files using:
Option Strict Off
Via Project Properties
You can only turn Option Strict on via the project properties in Visual Studio (sorry sandbox users). To turn Option Strict on via the project properties, follow these steps:
- Expand the Project menu
- Click on the project's properties menu item (last item)
- Click on the Compile tab
- Change the Option Strict dropdown to be On
- Save the project
The limitation to turning Option Strict on via the project properties is that Option Strict will only be turned on for that specific project. If you create a new project, Option Strict is turned off by default.
Via IDE Options
You can only turn Option Strict on via the IDE in Visual Studio (sorry again sandbox users). To turn Option Strict on via the IDE options, follow these steps:
- Expand the Tools menu
- Click on the Options menu item
- Expand the Projects and Solutions tree node
- Select the VB Defaults option
- Change the Option Strict dropdown to be On

Turning on Option Strict via the the IDE Options is the best option because any and all projects will have Option Strict on by default without the need for any additional steps.
Variables
Description
A variable is one way that a programmer can store data in VB.NET. Variables work by allowing the programmer to assign a keyword to some value. An example of creating a variable is:
Dim website As String = "VbLessons"
Dim slogan As String = "Teaching Visual Basic .NET, the right way."
In this example, two String variables are created: website and slogan. The table below represents the syntax of declaring a variable:
| Keyword | Required? | Description |
|---|---|---|
| Dim | Yes | The keyword that starts the variable declaration. |
| name | Yes | The user defined and unique keyword that represents the variable's name. |
| As | Depends | This keyword is required when specifying the data-type. |
| data-type | No | The data-type of the variable. |
| = | No | The assignment operator when initializing a variable. |
Examples
Following the syntax rules from above, here are a few examples on defining variables:
Dim variable1 As String
Dim variable2 = "Hello World!"
Notice that the second variable doesn't have the As keyword. This is because we are assigning the variable a value right away and the compiler can infer what the type is.
However, if you do not immediately assign the variable, then the As keyword is required. For example, this would be invalid code that would throw a compilation error:
Dim badVariable
Data-Types
VB.NET is considered a strongly typed language. That is to say that when the application that ultimately executes the code, it knows beforehand what data-type a variable will be.
As I have already mentioned, if you do not explicitly set the data-type when declaring a variable, the compiler (which is the application that ultimately executes the code) will have to infer (i.e., guess) what the data-type is and it may or may not always guess the data-type you intended. Because of this, I would encourage that you always explicitly declare variables.
The following represent the various data-types:
| Name | Description |
|---|---|
| Boolean | True or False |
| Byte | Whole number from 0 - 255 |
| Char | Single character |
| DateTime | 0:00:00 on January 1, 0001 through 11:59:59 PM on December 31, 9999 |
| Decimal | Numeric value with a fractional component (more accurate) |
| Double | Numeric value with a fractional component (less accurate) |
| Integer | Number without a fractional component |
| Long | Number without a fractional component (can be larger than Integer) |
| SByte | Whole number from -128 - 127 |
| Short | Number without a fractional component (smaller than Integer) |
| Single | Numeric value with a fractional component (less accurate and smaller than a Double) |
| String | Collection of Chars |
| UInteger | Whole number |
| ULong | Whole number (can be larger than UInteger) |
| UShort | Whole number (smaller than UInteger) |
Important to note: I would highly recommend going over the MSDN documentation linked in the caption of the table above. Some things, such as how certain data-types are represented (like Strings being wrapped in double-quotes), will be documented there.
Example
The following is an example of defining some variables with using different data-types to show you how some of their values are represented:
Dim trueBooleanExample As Boolean = True
Dim falseBooleanExample As Boolean = False
Dim singleCharacterExample As Char = "a"c
Dim dateTimeLiteralExample As DateTime = #11/17/2025 10:30:00 PM#
Dim dateTimeConstructorExample As DateTime = New DateTime(2025, 11, 17, 22, 00, 00)
Dim decimalExample As Decimal = 10.5
Dim doubleExample As Decimal = 6.7
Dim integerExample As Integer = -1
Dim uintegerExample As UInteger = 25012344
Input And Output
Description
Often times your program will require user interaction. They may need to enter some piece of information or read something before moving on.
Output
To print or write something to the console, use the Console.Write or Console.WriteLine method. Documentation here: https://docs.microsoft.com/en-us/dotnet/api/system.console.write and https://docs.microsoft.com/en-us/dotnet/api/system.console.writeline
Console.Write will print a String to the console whereas Console.WriteLine will do the same thing, only moving the cursor in the console to the next line.
Place the following code in your Main method:
Console.WriteLine("Hello World!")
If you are running the code in a sandbox, you should see the phrase "Hello World!" in the output area. But if you are running the code in Visual Studio, you may briefly see the phrase before the console closes.
The reason why the console closes so quickly in Visual Studio is because the code is finished executing in the Main method and there is no reason for the console to stay open. If you wanted to keep the console open, one way would be to prompt for the user enter something.
In newer versions of .NET, such as .NET 9, the console window actually stays open with a message stating the application finished executing. For now, if you are using Visual Studio, just add this after the line above:
Console.ReadLine()
Argument
Both the Console.Write and the Console.WriteLine methods accept additional arguments that allow you to format the text being output to the console.
An argument is not like talking politics during Thanksgiving. It's refers to a value being passed into a method. Don't worry too much about this yet, we will be going over it more in a later lesson.
To format the text in the Console.Write and the Console.WriteLine methods, inside the string we wrap curly brackets around an index and then the index points to the argument. For example, the following code will print "Hello David Day" and then "Hello World!"
Dim firstName As String = "David"
Dim lastName As String = "Day"
Console.WriteLine("Hello {0} {1}", firstName, lastName)
firstName = "World!"
Console.WriteLine("Hello {0}", firstName)
The first line prints "Hello David Day" because {0} points to the first argument which is the variable firstName and {1} points to the second argument which is the variable lastName.
Keep in mind that the ordering matters, if we swapped the curly brackets inside the string then it will print differently. For example:
Dim firstName As String = "David"
Dim lastName As String = "Day"
Console.WriteLine("Hello {1}, {0}", firstName, lastName)
So even though our arguments didn't change, the order in which they appear in the string did. This example would print: Hello Day, David
Input
To read input from the console, use the Console.ReadLine method. Documentation here: https://docs.microsoft.com/en-us/dotnet/api/system.console.readline
The Console.ReadLine method will read the input and return a String with the value.
For example, here is how you could prompt for a value:
Dim dayOfTheWeek As String
Console.Write("What day of the week is it: ")
dayOfTheWeek = Console.ReadLine()
Console.WriteLine("You tell me that the day of the week is {0}", dayOfTheWeek)
Exercise
Try to do the following:
- Prompt the user for their name.
- Store the user input in a variable.
- Write back to the user "hello [name]!"
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Console.Write("Name: ")
Dim name As String = Console.ReadLine()
Console.WriteLine("Hello {0}!", name)
End Sub
End Module
DotNetFiddle Live Demo
Arithmetic
Description
Do you want to be a programmer or not? If so, then surely you should have known that there would be some math involved.
Operators
The table below represent various arithmetic operators:
| Function | Operator |
|---|---|
| Add | + |
| Subtract | - |
| Multiply | * |
| Divide | / |
| Modulous | MOD |
| Exponent | ^ |
The result of an expression can have differing data-types.
For example, division will always be a fractional data-type like a decimal or short since division has the potential to return a fractional value. Whereas addition may return integral or fractional data-types depending on the result.
This is why, to reiterate from the Variables lesson, it is important to explicitly define what data-type you expect.
Example
Here is an example of using the various operators:
Dim addition As Integer = 1 + 2
Console.WriteLine("1 + 2 = {0}", addition)
Dim subtraction As Integer = 2 - 1
Console.WriteLine("2 - 1 - {0}", subtraction)
Dim multiplication As Integer = 2 * 3
Console.WriteLine("2 * 3 = {0}", multiplication)
Dim division As Double = 6 / 2
Console.WriteLine("6 / 2 = {0}", division)
Dim modulous As Integer = 4 MOD 2
Console.WriteLine("4 MOD 2 = {0}", modulous)
Dim exponent As Integer = 6 ^ 7
Console.WriteLine("6 ^ 7 = {0}", exponent)
The following would be printed in the console if the above code was executed:
1 + 2 = 3
2 - 1 - 1
2 * 3 = 6
6 / 2 = 3
4 MOD 2 = 0
6 ^ 7 = 279936
Order Of Operations
Math is extremely simple in VB.NET but it is important to remember that when you assign a variable to some mathematical expression you need to be mindful of operator precedence.
In school they may have taught you PEMDAS or BODMAS, parenthesis get performed before exponents, exponents get preformed before multiplication and division, multiplication and division get preformed before addition and subtraction. The same order of operations applies when coding.
Exercise
Try to do the following:
Solution
Show Pythagorean Theorem Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim a = 5
Dim b = 3
Dim c = (5 ^ 2) + (3 ^ 2)
Console.WriteLine("Pythagorean Theorem: {0} square + {1} squared = {2}", a, b, c)
End Sub
End Module
DotNetFiddle Live Demo
Show Galileo's Speed Formula Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim distance = 5
Dim time = 73
Dim speed = distance / time
Console.WriteLine("Galileo's Speed Formula: {0} over {1} = {2}", distance, time, speed)
End Sub
End Module
DotNetFiddle Live Demo
Comments
Description
Comments allow you to write text that the program will ignore.
Comments have many use cases. Some use cases are:
- Indicate who wrote a piece of code
- Explain what a block of code does in plain English
- Indicate where a section starts and stops
Comments can appear anywhere in the code, but it is important to note that you cannot prematurely end a comment. A comment starts with an apostrophe and ends at the end of a line.
Example
The following is an example of using comments:
' Author: David Day
Option Strict On ' turning option strict on
Imports System
Public Module Module1
' TODO: setup a main method
End Sub
Comments may make the code look bigger, but comments do not add to the size of the final program. Comments are actually stripped out of the code whenever the code gets built. So you should not be worried about overall code size of the code with comments as they have no impact in the long run.
Task List Comments
This will only apply if you are using Visual Studio or an IDE that supports task lists. Comments can be used to build a task list. They work by starting the comment with a keyword like TODO, HACK, or even custom keywords. When comments start with a task list keyword, they will appear in the IDE's task list window; in Visual Studio the task list window is found under View > Task List.
Task list comments can be very useful when managing large projects. This example can give you a good idea how how task list comments are used in practical situations:
' TODO the code below is difficult to follow, this is probably a candidate for refactoring
' ... some convoluted code here
Be mindful when using task list comments. You can start to clutter up the task list to the point to where you or other developers start to ignore the listed items.
If/Then Statements
Description
The simplest form of a conditional statement in VB.NET is the If/Then statement. The If/Then statement has several variations but there are a few rules based on which variation you need.
If
The first and simplest variation of an If/Then statement is to have a single statement. The following is the syntax for a single statement If statement:
If (value1 = value2) Then
' value1 equals value2, do something!
End If
It is important to note that the parethesis around the conditional statement are not required. This is a stylistic format that I personally use to help readability.
The If only statement only evaluates a single expression and if the expression is true then it executes the code inside the If/Then block.
Take this for example:
Console.Write("Username: ")
Dim username As String = Console.ReadLine()
If (username = "admin") Then
Console.WriteLine("Running with elevated privileges.")
End If
Console.WriteLine("Welcome, {0}", username)
This example prompts for a username, then only prints "Running with elevated privileges" if the entered username exactly matches "admin", and then will always print out the welcome statement at the end.
ElseIf
The second and more complex variation of an If/Then statement is to have ElseIf checks. ElseIfs will check the expressions in the order in which they appear, but they must appear after the initial If statement. The following is the syntax using ElseIfs:
If (value1 = value2) Then
' value1 equals value2, do something!
ElseIf (value1 = value3) Then
' value1 equals value3, but does not equal value1
ElseIf (value2 = value3) Then
' value2 equals value3
End If
You can have zero or more ElseIf statements, meaning it is completely optional or you can setup 50 million different checks.
The reason why order matters is because once an If or ElseIf block is executed, it will not execute any of the other blocks of code. For example:
Dim value1 As String = "A1"
If (value1 = "A") Then
' this is not true
ElseIf (value1 = "A1") Then
' this is true and the first condition to be true
' any code in here will be executed
ElseIf (value1.StartsWith("A")) Then
' this is true, but the first ElseIf is also true
' no code in here will be executed
End If
Else
The third variation of an If/Then statement is to have an Else check. The Else statement will always go at the very end and will only execute if all other checks in the If chain fail. The following is the syntax using an Else statement:
If (value1 = value2) Then
'value1 equals value2, do something!
ElseIf (value1 = value3) Then
'value1 equals value3, but not value 2
Else
'value1 does not equal value2 or value3
End If
You can have zero or one Else statements, meaning its optional but you can't have more than one.
The Else statement will always be the last block of the If/Then chain too.
Remember, ElseIf statements are completely optional. You can have an If...Else without any ElseIf checks in there. For example:
Console.Write("Username: ")
Dim username As String = Console.ReadLine()
If (username = "admin") Then
Console.WriteLine("Running with elevated privileges.")
Else
Console.WriteLine("Running normally")
End If
Console.WriteLine("Welcome, {0}", username)
Exercise
Try to do the following:
- Prompt for the user's first name.
- Check if it matches your name.
- Check if it matches somebody elses name
- Check if matches neither name.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Console.Write("First Name: ")
Dim firstName As String = Console.ReadLine()
If (firstName = "David") Then
Console.WriteLine("We share the same name!")
ElseIf (firstName = "Michael") Then
Console.WriteLine("You share my brother's name!")
Else
Console.WriteLine("You have a pretty cool name.")
End If
End Sub
End Module
DotNetFiddle Live Demo
Select/Case
Description
An alternative to the If/Then statement is the Select/Case statement. The Select/Case statement provides you a more organized way of checking an expression.
The way it works is you have a single expression at the top. VB.NET will then evaluate each "case" in order to see if it equals the expression. Once the first case matches, then it exits the whole Select/Case statement.
This is an important distinction because if you have some JavaScript or C# experience, you may be used to breaking out of a Select/Case statement, that is not necessary in VB.NET.
Example
The following is the syntax for a Select/Case statement:
Select Case value1
Case value2
' value1 equals value2, do something!
Case value3
' value1 equals value3, but not value2
Case Else
' value1 does not equal value2 or value3
End Case
It is important to note that the Case Else is not required, but at least one Case is required.
Multiple Values Check
Cases can be used to check multiple values at once using a CSV pattern:
Select Case dayOfWeek
Case "Saturday", "Sunday"
Console.WriteLine("Weekend")
Case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
Console.WriteLine("Weekday")
End Select
Alternatively, you can use ranges as well:
Select Case score
Case 90 To 100
Console.WriteLine("A")
Case 80 To 89
Console.WriteLine("B")
Case 70 To 79
Console.WriteLine("C")
Case 60 To 69
Console.WriteLine("D")
Case Else
Console.WriteLine("F")
End Select
You can also do an open-eneded range:
Select Case score
Case Is > 90
Console.WriteLine("A")
Case Is > 80
Console.WriteLine("B")
Case Is > 70
Console.WriteLine("C")
Case Is > 60
Console.WriteLine("D")
Case Else
Console.WriteLine("F")
End Select
Exercise
Try to do the following:
- Imagine you are giving the user a test.
- You ask them 10 questions.
- At the end of the test, get their perecentage.
- Give the user their percentage and grade equivalent.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim correctAnswers As Integer = 0
Console.WriteLine("Basic Math Test")
Console.Write("1 x 1: ")
If (Console.ReadLine() = "1") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 2: ")
If (Console.ReadLine() = "2") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 3: ")
If (Console.ReadLine() = "3") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 4: ")
If (Console.ReadLine() = "4") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 5: ")
If (Console.ReadLine() = "5") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 6: ")
If (Console.ReadLine() = "6") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 7: ")
If (Console.ReadLine() = "7") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 8: ")
If (Console.ReadLine() = "8") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 9: ")
If (Console.ReadLine() = "9") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 10: ")
If (Console.ReadLine() = "10") Then
correctAnswers = correctAnswers + 1
End If
If (correctAnswers = 0) Then
Console.WriteLine("Really? 0.")
Else
Dim score As Double = correctAnswers / 10
Console.Write("{0}: ", score * 100)
Select Case score
Case Is >= 0.9
Console.WriteLine("A")
Case Is >= 0.8
Console.WriteLine("B")
Case Is >= 0.7
Console.WriteLine("C")
Case Is >= 0.6
Console.WriteLine("D")
Case Else
Console.WriteLine("F")
End Select
End If
End Sub
End Module
DotNetFiddle Live Demo
Ternary If
Description
The least verbose form of a conditional statement in VB.NET is the Ternary If statement. Unlike the If statement and the Select/Case statement, there is only one version of the Ternary If statement.
A Ternary If works by checking one expression and if it is true, then return one value, but if it is false then it will return a different value.
Example
The following is an example of a Ternary If:
Dim result As Boolean = If(value1 = value2, True, False)
Abuse
Ternary If statements are extremely concise, but they have the potential to be abused. You can use a nested Ternary If by using a Ternary If inside of one of the return values.
I would highly discourage using nested Ternary Ifs, it would be much more legible to breakup a nested Ternary If into an If/Then or Select/Case statement.
Exercise
Try to do the following:
- Imagine you are giving the user a test.
- You ask them 10 questions.
- At the end of the test, show the user if they passed or failed.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim correctAnswers As Integer = 0
Console.WriteLine("Basic Math Test")
Console.Write("1 x 1: ")
If (Console.ReadLine() = "1") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 2: ")
If (Console.ReadLine() = "2") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 3: ")
If (Console.ReadLine() = "3") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 4: ")
If (Console.ReadLine() = "4") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 5: ")
If (Console.ReadLine() = "5") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 6: ")
If (Console.ReadLine() = "6") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 7: ")
If (Console.ReadLine() = "7") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 8: ")
If (Console.ReadLine() = "8") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 9: ")
If (Console.ReadLine() = "9") Then
correctAnswers = correctAnswers + 1
End If
Console.Write("1 x 10: ")
If (Console.ReadLine() = "10") Then
correctAnswers = correctAnswers + 1
End If
Dim result As String = If(correctAnswers >= 6, "Pass", "Fail")
Console.WriteLine("Result of test: {0}", result)
End Sub
End Module
DotNetFiddle Live Demo
Operators
Description
I have already shown some of the operators in previous example and you probably guessed what they were fairly easily.
Now we will be going over the two types of operators in VB.NET.
Comparison Operators
Comparison operators are used to compare two values. The result will return a Boolean value (i.e., true or false) that represents the relationship between the two values being compared.
The table below represent various comparison operators:
| Function | Operator |
|---|---|
| Equal To | = |
| Not Equal To | <> |
| Less Than | < |
| Less Than or Equal To | <= |
| Greater Than | > |
| Greater Than or Equal To | >= |
Think of comparison operators in plain English: Is the value of the variable1 equal to the value of variable2? Is the value value of variable1 not equal to 5? Etc.
Equality Check
You may have noticed that the "is equal to" comparison operator is the same as the "assignment" operator when assigning variables; this is a holdover from legacy BASIC languages. It is unfortunate, but Microsoft decided to keep the operator the same in VB.NET instead of changing it.
Ironically, they did not do this C# (the C equivalent of VB.NET). In fact most languages outside of BASIC style langauges have a special operator for equality check, typically == or even === for stricter checks.
Something you should watch out for is assigning variables based on equality checks. For example:
Dim result = foo = bar
This code is actually assigning the variable result to the equality check of foo and bar. In other words, if foo equals bar, then result will be set to true otherwise it will be set to false.
With that being say, there is an Equals method that you can use in lieu of the = operator, e.g.:
Dim value As String = Console.ReadLine()
If (value.Equals("foo")) Then
' ...
End If
This is purely stylistic, you can use whichever way you prefer.
Example
Here is an example of doing comparison checks:
If (value1 = value2) Then
' value1 equals value2
ElseIf (value2 <> value3) Then
' value2 does not equal value3
ElseIf (value3 < value4) Then
' value3 is less than value4
ElseIf (value4 > value5) Then
' value4 is greater than value5
ElseIf (value5 <= value6) Then
' value5 is less than or equal to value6
ElseIf (value6 >= value7) Then
' value6 is greater than or equal to value7
End If
Logical Operators
Logical operators are used to compare two expressions and return a Boolean value.
The table below represent various logical operators:
| Function | Operator |
|---|---|
| Conjunction - If both expressions are True | AndAlso |
| Disjunction - If one of the two expressions are True | OrElse |
These logical operators are considered short-circute operators. In the case of AndAlso, if the first condition is false then it will not bother to evaluate the second condition. This is because no matter the result of the second condition, the comparison as a whole will fail. The same thing applies to OrElse.
Example
Here is an example of doing logical checks:
If (value1 = value2 AndAlso value2 = value3) Then
' value1 equals value 2
' AND value2 equals value3
ElseIf (value1 = value2 OrElse value2 = value3) Then
' value1 equals value2
' OR value2 equals value3
ElseIf (value1 = value2 AndAlso (value2 = value3 OrElse value3 > value4)) Then
' value1 equals value2
' AND either of these are true:
' value2 equals value3
' value3 greater than value4
End If
Arrays
Description
Arrays have existed for a very long time. They were actually apart of a version of BASIC known as Dartmouth BASIC all the way back in 1966!
Arrays are fixed sized collections and are efficient if you do not need to add or remove values. In other words, they should be used when you have a collection of values, you know exactly how many values there are, and the number of values will never change.
Example
The following is example of how to declare an array:
Dim myCollection() As Integer
To initialize an array, set the array equal to all the values that will make up the array and enclose the values in curly brackets {}.
The following example is how to declare a collection of letters that make up the English alphabet:
Dim alphabet() As String = { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" }
Zero-Based Index
I showed you this without really explaining it back in the Input And Output lesson, but collections utilize a zero-based index. This means the first item in the collection is at index 0. Using the example above, index 0 would be the first item or the letter "a" and index 1 would be the second item or the letter "b".
This is an example of getting items from the array:
Dim alphabet() As String = { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" }
Dim index As Integer = 0
Dim character As String = alphabet(index)
Console.WriteLine("Item {0}: {1}", index, character) ' Item 0 = a
index = 1
character = alphabet(index)
Console.WriteLine("Item {0}: {1}", index, character) ' Item 1 = b
index = 25
character = alphabet(index)
Console.WriteLine("Item {0}: {1}", index, character) ' Item 25 = z
Upper-Bounds
Sometimes you will know the number of items in an array beforehand, othertimes you won't. The maximum number of items an array can hold is called the upper-bounds.
You can explicitly set the upper-bounds of an array when declaring it, but if you do then you cannot initialize the collection like we do in the example above.
For example:
Dim alphabet(25) As String ' string array with an upper-bounds of 25 (i.e., 26 items)
alphabet(0) = "a"
alphabet(1) = "b"
' etc...
For most situations, you won't see much of a performance improvement by explicitly setting the upper-bounds of an array. But, this is a way to define an array and I wanted to show it to you.
Exception
If you try to get an item in the array by its index and the index you're trying to get doesn't exist (i.e. less than 0 or greater than upper-bounds), then an error will be thrown at runtime called an IndexOutOfRangeException: Documentation here: https://docs.microsoft.com/en-us/dotnet/api/system.indexoutofrangeexception
Runtime exceptions are harder to track down because they don't happen when we try to compile the code. Instead they happen when the code is actually running.
Luckily for us, it is very easy to prevent IndexOutOfRangeExceptions. All we have to do is check if the index we're using is greater than -1 and less than or equal to the upper-bounds.
For example:
Dim alphabet() As String = { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" }
Dim index As Integer
' ... index is set somewhere down the line
If (index >= 0 OrElse index <= alphabet.Length - 1) Then
Console.WriteLine(alphabet(index))
Else
Console.WriteLine("You are using an invalid index.")
End If
Exercise
Try to do the following:
- Create an array to store all the letters in the English alphabet
- Use Console.Write to print your name, letter by letter
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim alphabet() As String = {"a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z"}
Console.Write(alphabet(3)) 'd
Console.Write(alphabet(0)) 'a
Console.Write(alphabet(21)) 'v
Console.Write(alphabet(8)) 'i
Console.WriteLine(alphabet(3)) 'd
End Sub
End Module
DotNetFiddle Live Demo
Lists
Description
Just like Arrays, Lists also represent a collection of values. The difference is that Lists do not have a fixed size, meaning you can easily add and remove items from the collection.
An example of when a List might be applicable would be like an inventory system. Let's say that you wanted to keep track of the bags of rice in a store, in this case we would add to the list everytime we received a shipment and then remove from the list anytime someone purchases a bag. An array doesn't make sense here because it would never have a fixed size.
Example
The following is the syntax for declaring a List:
Dim list1 As New List(Of String)
Required Import
If you get an error with the above line that says:
Type 'List' is not defined.
Then this is because the System.Collections.Generic namespace has not been imported.
The default settings in Visual Studio will have the namespace imported by default, but if you are using a sandbox or have tinkered with the default settings, then you will need to manually import the namespace. This goes at the top of the code file:
Imports System
Imports System.Collections.Generic ' add me
Public Module Module1
Public Sub Main()
Dim list1 As New List(Of Integer)
End Sub
End Module
Remember, if you have Option Strict turned on inside the code file, the Imports statement would go after the Option Strict statement but before anything else.
Generic Type
The List(Of T) class is considered a Generic, meaning that the data-type that the list represents is defined when you initialize the List.
For example:
Dim list1 As New List(Of String) ' list1 can only hold String values
Dim list2 As New List(Of Integer) ' list2 can only hold Integer values
Dim list3 As New List(Of DateTime) ' list3 can only hold DateTime values
Types of Variables
Up until now we have been mainly working with "primitive" variables. In other words, things like Strings, Integers, Booleans, etc.
Primitives are considered Value types, meaning they directly contain their data and we don't need to do anything special.
List(Of T) is a class, which makes it a Reference type. Reference types are different because we need to call the "new" keyword to instantiate the variable. This is why in the examples above you see New List(Of T).
Without applying the new keyword, the class's constructor will never get called and so we would just have a variable that holds no value. Incidentally, "no value" is called Nothing in VB.NET and Null in most other programming languages.
For example, this example would throw a NullReferenceException:
Dim list1 As List(Of String) ' forgot the "new" keyword
list1.Add("Item 1") ' NullReferenceException thrown here
That is because we have a variable that has no value, but we're trying to use a member of that variable.
Default State
List(Of T) variables can be initialized with a default collection by providing it with an initial array using the "From" keyword.
For example:
Dim list1 As New List(Of Integer) From { 10, 20, 30 }
The above example will create a new List and hydrate it with the values 10, 20, 30.
Keep in mind that you do not need to do this all on one line. Depending on your IDE, you could separate the values by using just a new line or by using the line continuation character, which is an underscore. For example:
' this uses the line continuation character
Dim list1 As New List(Of Integer) From { _
10, _
20, _
30 _
}
' this uses just a new line, which may or may not work in your developing environment
Dim list2 As New List(Of String) From {
"Ten",
"Twenty",
"Thirty"
}
Getting An Item
Use the List(Of T).Item property to get a value at the specified index.
For example:
Dim list1 As New List(Of Integer) From { 10, 20, 30 }
Dim ten As Integer = list1.Item(0)
Lists are just like arrays in that they have a zero-based index and an IndexOutOfRangeException will be thrown if you attempt to get an index outside the bounds of the collection.
Adding To The Collection
Lists are designed to be modified and there are several ways to add items.
Add Method
The List(Of T).Add method will allow you to add a single item to the end of the collection.
For example:
Dim list1 As New List(Of Integer) From { 0 }
' list1 = { 0 }
list1.Add(10)
list1.Add(20)
list1.Add(30)
' list1 = { 0, 10, 20, 30 }
In the example above, we initialize our list with a default collection of 0. Afterwards, we add three more items to the collection, one at a time, and end up with 0, 10, 20, 30.
AddRange Method
The List(Of T).AddRange method will allow you to add a multiple items to the end of the collection.
This works by providing the method with a collection. For example:
Dim list1 As New List(Of Integer) From { 0 }
' list1 = { 0 }
list1.AddRange({ 10, 20, 30 })
' list1 = { 0, 10, 20, 30 }
In the example above, we initialize our list just like in the example before it. Afterwards we add three more items to the collection, all at once, and end up with the same results as the example before.
Keep in mind that the example I gave above is just using a shorthand for an array. We could define the array or even a list outside the AddRange method call. For example:
Dim list1 As New List(Of Integer)
' list1 = {}
Dim array1() As Integer = { 0 }
list1.AddRange(array1)
' list1 = { 0 }
Dim list2 As New List(Of Integer) From { 10, 20 }
list2.Add(30)
list1.AddRange(list2)
' list1 = { 0, 10, 20, 30 }
Insert Method
The List(Of T).Insert method will allow you to add an item to the collection, at the specified index.
For example:
Dim list1 As New List(Of String) From { "One", "Two", "Four", "Five" }
list1.Insert(2, "Three")
' list1 = { "One", "Two", "Three", "Four", "Five" }
Remember that List(Of T) indexing behaves just like Arrays. It is a zero-based index and you must stay withing the bounds of the collection.
InsertRange Method
The List(Of T).InsertRange method will allow you to add multiple items to the collection, at the specified index.
This works very similarly to the AddRange method, only you get to specify where the values should be added. For example:
Dim list1 As New List(Of Integer) From { 3, 4 }
' list1 = 3 and 4
list1.InsertRange(0, { 1, 2 })
' list1 = 1, 2, 3, 4
Removing From The Collection
Just like with adding items, there are several ways to remove items from a List(Of T).
Clear Method
The List(Of T).Clear method will remove every item from the collection.
For example:
Dim list1 As New List(Of Integer) From { 0, 1, 2, 3, 4, 5 }
' list1 = { 0, 1, 2, 3, 4, 5 }
list1.Clear()
' list1 = {}
In the example above, we initialize our list with a default collection of 0, 1, 2, 3, 4, 5. Afterwards, clear the collection and end up with an empty list.
Remove
The List(Of T).Remove method will remove the first occurence of a value from the collection.
For example:
Dim list1 As New List(Of Integer) From { 2, 1, 3, 1, 4, 1, 5, 1, 6 }
' list1 = { 2, 1, 3, 1, 4, 1, 5, 1, 6 }
list1.Remove(1)
' list1 = { 2, 3, 1, 4, 1, 5, 1, 6 }
list1.Remove(1)
' list1 = { 2, 3, 4, 1, 5, 1, 6 }
list1.Remove(1)
' list1 = { 2, 3, 4, 5, 1, 6 }
list1.Remove(1)
' list1 = { 2, 3, 4, 5, 6 }
In the example above, we initialize our list with a default collection of 2, 1, 3, 1, 4, 1, 5, 1, 6. We then call the Remove method and tell it to remove the value 1. However, since the value 1 appears multiple times in the collection, only the first instance of the value 1 is removed. It takes 4 calls of the Remove method to completely remove the value 1 from the collection.
Remove At
The List(Of T).RemoveAt method will remove a value from the collection by the specified index.
For example:
Dim list1 As New List(Of Integer) From { 1, 2, 3, 4, 5 }
' list1 = { 1, 2, 3, 4, 5 }
list1.RemoveAt(2)
' list1 = { 1, 2, 4, 5 }
In the example above, we initialize our list with a default collection of 1, 2, 3, 4, 5. We then call the RemoveAt method to remove the item at the second index, which with a zero based index would be the "third" slot, or the value 3.
Contains Method
Sometimes, we need to check if an item exists in a List(Of T) before we add or remove new items from the collection.
The List(Of T).Contains method will return a Boolean result based on if the value exists in the collection.
For example:
Dim list1 As New List(Of String) From { "One", "Two", "Four", "Five" }
Console.WriteLine("Enter a value of: One, Two, Three, or Four")
Dim userInput As String = Console.ReadLine()
If (list1.Contains(userInput)) Then
Console.WriteLine("Thank you!")
Else
Console.WriteLine("Invalid selection")
End If
Something to keep in mind is that the Contains method is case-sensitive with String values. In the example above, you would get Invalid selection if you entered "one" instead of "One".
Exercise
Try to do the following:
- Create a List that represents a parking garage full of vehicles.
- Initialize the List with several vehicles.
- Use the various add and remove methods to illustrate a parking garage's state throughout the day.
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Public Module Module1
Public Sub Main()
' initialize List with default values
Dim garage As New List(Of String) From {
"1978 Ford Mustang II",
"1964 AMC Rambler",
"1970 Chevrolet Corvette"
}
' prompt the user for a value to remove
Console.WriteLine("What vehicle are you withdrawing: ")
Dim userInput As String = Console.ReadLine()
If (garage.Contains(userInput)) Then
' remove the value if it exists
Console.WriteLine("Removing {0}", userInput)
garage.Remove(userInput)
Else
Console.WriteLine("I could not find that vehicle.")
End If
' prompt the user for a value to add
Console.WriteLine("---")
Console.WriteLine("What vehicle are you depositing: ")
userInput = Console.ReadLine()
If (garage.Contains(userInput)) Then
Console.WriteLine("I cannot add that vehicle, because I already have that same year/make/model.")
Else
' add the value if it does not already exist
Console.WriteLine("Adding {0}.", userInput)
garage.Add(userInput)
End If
End Sub
End Module
DotNetFiddle Live Demo
Dictionaries
Description
Just like the List(Of T), a Dictionary(Of TKey, TValue) also represent a non-fixed size collection of values. The difference is that Dictionaries store key/value pairs instead of individual values.
With key/value pairs, the key must be unique to the Dictionary. It doesn't matter if the value repeats, but the key must never repeat.
An example of when a Dictionary might be applicable would like a menu of a restaurant. The key would be the food dish and the value would be the cost. The food dish is the key because you wouldn't have two of the exact dishes at different costs and the cost is the value because you have two different dishes cost the same. Since the Dictionary does not have a fixed size, the menu can add or remove the key/value pairs based on the season.
Example
The following is an exmaple of creating a new Dictionary(Of TKey, TValue):
Dim dictionary1 As New Dictionary(Of String, Double)
The code above creates a new Dictionary and specifies that the key is a String and the value is a Double, much like the menu example described above.
Keep in mind that the Dictionary(Of TKey, TValue) also lives in the System.Collections.Generic namespace and so it must be imported if you want to use the Dictionary.
Default State
Dictionary(Of TKey, TValue) can be initialized with a default collection by providing it with an initial array using the "From" keyword.
For example:
Dim dictionary1 As New Dictionary(Of Integer, String) From { {1, "David"}, {2, "Day"}, {3, "David"}, {4, "Day"} }
Or if you wanted to use multiple lines:
' line continuation
Dim dictionary1 As New Dictionary(Of Integer, String) From { _
{ 1, "David" }, _
{ 2, "Day" }, _
{ 3, "David" }, _
{ 4, "Day" } _
}
' this uses just a new line, which may or may not work in your developing environment
Dim dictionary2 As New Dictionary(Of String, Double) From {
{ "Foo", 1 },
{ "Bar", 10.55 },
{ "Lorem", -51112.24 }
}
Getting An Item
Use the Dictionary(Of TKey, TValue).Item property to get a value by the specified key.
For example:
Dim dictionary1 As New Dictionary(Of Integer, String) From { { 1, "David" }, { 2, "Day" }, { 3, "David" }, { 4, "Day" } }
Dim value As String = dictionary1(1) ' value = "David"
Notice in this example, unlike in the List's example, we did not type out .Item when getting the value. We very well could have, but I wanted to demonstrate a common short-hand that you'll see. The example above is functionally equivalent to:
Dim value As String = dictionary1.Item(1) ' value = "David"
Adding To The Collection
Dictionaries are allowed to be modified, but unlike the List class which has multiple methods to add values, the Dictionary class only provides us with the Dictionary(Of TKey, TValue).Add method.
This works similarly to the List's Add method in that it will add a single key/value pair to the end of the collection. For example:
Dim dictionary1 As New Dictionary(Of Integer, String) From { { 1, "One" } }
' dictionary1 = { { 1, "One" } }
dictionary1.Add(2, "Two")
dictionary1.Add(3, "Three")
dictionary1.Add(4, "Four")
' dictionary1 = {
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" },
{ 4, "Four" }
}
In the example above, we initialize our list with a default collection of { 1, "One" }. Afterwards, we add three more items to the collection, one at a time, and up with: { 1, "One" }, { 2, "Two" }, { 3, "Three" }, { 4, "Four" }.
Exception
If you try to add a key/value pair to the Dictionary and the Dictionary already has a pair with that key, then an error will be thrown at runtime called an ArgumentException: Documentation here: https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.
Lucky for us, it is very easy to prevent ArgumentExceptions, all we have to do is check if the key already exists in the Dictionary using the Dictionary(Of TKey, TValue).ContainsKey method.
For example:
Dim dictionary1 As New Dictionary(Of String, String) From { { "A", "One" } }
Console.Write("Key: ")
Dim key As String = Console.ReadLine()
Console.Write("Value: ")
Dim value As String = Console.ReadLine()
If (dictionary1.ContainsKey(key)) Then
Console.WriteLine("Cannot add the key/value pair because the key already exists.")
Else
Console.WriteLine("Adding {0}/{1}", key, value)
dictionary1.Add(key, value)
End If
Removing From The Collection
There are a couple of ways to remove key/value pairs from a Dictionary.
Clear
The Dictionary(Of TKey, TValue).Clear method will remove every item from the collection.
For example:
Dim dictionary1 As New Dictionary(Of Integer, String) From { { 1, "David" }, { 2, "Day" } }
' dictionary1 = {
{ 1, "David" },
{ 2, "Day" }
}
dictionary1.Clear()
' dictionary1 = {}
In the example above, we initialize our list with a default collection of { 1, "David" }, { 2, "Day" }. Afterwards, we clear the collection and end up with an empty Dictionary.
Remove
The Dictionary(Of TKey, TValue).Remove method will remove the key/value pair from the collection based on the given key.
For example:
Dim dictionary1 As New Dictionary(Of Integer, String) From { { 1, "David" }, { 2, "Day" } }
' dictionary1 = {
{ 1, "David" },
{ 2, "Day" }
}
dictionary1.Remove(1)
' dictionary1 = { { 2, "Day" } }
In the example above, we initialize our list with a default collection of { 1, "David" }, { 2, "Day" }. Afterwards, we remove the key/value pair where the key equal 1 and end up with { 2, "Day" }.
Keep in mind that an ArgumentException will be thrown if you attempt to remove a key/value pair where the key does not exist. It is important to check that the dictionary contains the key first before removing it.
Exercise
Try to do the following:
- Create a Dictionary that represents a restaurant menu.
- Initialize the List with several menu items.
- Prompt the user for what item they want to buy.
- Give the user readable error if they ask for an item that is not in the dictionary.
- Give the user the price if they ask for an item that is in the dictionary.
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Public Module Module1
Public Sub Main()
Dim menu As New Dictionary(Of String, Double) From {
{ "Cold Drink", 1.5 },
{ "Hamburger", 5.0 },
{ "Hot Dog", 3.5 },
{ "Nachos", 3.5 }
}
Console.Write("What do you want: ")
Dim request As String = Console.ReadLine()
If (menu.ContainsKey(request)) Then
Console.WriteLine("{0} costs ${1}", request, menu.Item(request))
Else
Console.WriteLine("{0} is not on the menu.", request)
End If
End Sub
End Module
DotNetFiddle Live Demo
For/Next Loop
Description
A loop is essentially a way to repeat a block of code. This allows us to simplify our code and make it easier to read.
A For/Next loop is used to loop specific number times.
For example:
For loopVariableCounter As Integer = 1 To 10 Step 1
Console.WriteLine("Loop number {0}", loopVariableCounter)
Next
The code above will loop 10 times and print the variable, which represent what loop counter it is on. I.e. it will print:
Step
In the example above we specify a step at the end of the first line. The step tells the compiler what value to increment counter at. The default step of a For/Next loop is 1, which means the example above could be simplified to:
For loopVariableCounter As Integer = 1 To 10
Console.WriteLine("Loop number {0}", loopVariableCounter)
Next
However, what if we wanted the step to a fraction? Then we would change the counter variable to a Double and set the step to the fractional amount:
For counter As Double = 1 To 10 Step 0.5
Console.WriteLine("counter = {0}", loopVariableCounter)
Next
The code above will print out 20 values from 1 to 10 in increments of 0.5, e.g. 1, 1.5, 2, 2.5, etc.
What if we wanted to loop backwards? Then we'd make the "to" value less than the initial value of the counter and set the step to a negative value.
For example, this is how we'd loop backwards from 10 in 0.5 increments:
For counter As Double = 10 To 1 Step -0.5
Console.WriteLine("counter = {0}", loopVariableCounter)
Next
Exercise
Try to do the following:
- Create an Array that holds the alphabet.
- Create a List that holds characters.
- Loop over the array, backwards, and add the current character to the List.
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Public Module Module1
Public Sub Main()
Dim alphabet() As String = { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" }
Dim reversedAlphabet As New List(Of String)
For counter As Integer = alphabet.Length - 1 To 0 Step -1
Dim letter As String = alphabet(counter)
reversedAlphabet.Add(letter)
Next
End Sub
End Module
DotNetFiddle Live Demo
For/Each Loop
Description
The For/Each loop allows us to loop over every item in a collection.
For example:
Dim people() As String = { "David", "Brent", "John" }
For Each person As String In people
Console.WriteLine(person)
Next
The For/Each loop is convenient because you do not need to know how many items are in the collection.
Unlike the For/Next loop, in the For/Each loop you do not have know how many times you have to loop for.
Exercise
Try to do the following:
- Create an Array that holds the several numbers.
- Create a variable that will store the sum of all the numbers.
- Loop over the array and add each number to the variable.
- After the loop finishes, display the final sum value.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim values() As Integer = { 1, -1, 55, 90, -75 }
Dim sum As Integer
For Each value As Integer In values
sum = sum + value
Next
Console.WriteLine("Sum: {0}", sum)
End Sub
End Module
DotNetFiddle Live Demo
Do Loop
Description
There are several variations of a Do loop, but the basic idea is that it will continue to loop based on a Boolean value.
Do/Until Loop
The first variation is the Do/Until loop. This will continue to loop until a Boolean is true and the check against the Boolean value can happen at the beginning or the end of the loop.
For example:
' example of checking at top of loop
Dim counter As Integer = 0
Do Until counter = 10
counter = counter + 1
Console.WriteLine("Counter incremented by 1")
Loop
' example of checking at bottom of loop
Dim keyword As String
Do
Console.Write("Type 'exit' to escape: ")
keyword = Console.ReadLine()
Loop Until keyword = "exit"
Do/While Loop
The second variation of a Do loop is the Do/While loop. This will continue to loop while a Boolean is true. Just like with the Do/Until variation, the check can happen at the beginning or the end of the loop.
For example:
' example of checking at top of loop
Dim counter As Integer = 0
Do While counter < 10
counter = counter + 1
Console.WriteLine("Counter incremented by 1")
Loop
' example of checking at bottom of loop
Dim keyword As String
Do
Console.Write("Type 'exit' to escape: ")
keyword = Console.ReadLine()
Loop While keyword <> "exit"
Infinite Loop
Be very careful when using Do loops because they have the potential to be an infinite loop.
Infinite loops can cause serious issues like StackOverflowExceptions as well as battery overheating issues on laptops.
While infinite loops have their purpose, they should be used with caution.
The following is an example of setting up an infinite loop:
Do While True
' do something
Loop
' or
Do Until True = False
' do something
Loop
If you are running Visual Studio, open you task manager while running the application and watch the CPU jump to 100%.
Exercise
Try to do the following:
- Setup a Do loop, either variation, that stops when the user guesses your name.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Console.WriteLine("Try to guess my name!")
Dim myName As String = "David"
Dim userInput As String
Do
Console.Write("Guess: ")
userInput = Console.ReadLine()
Loop Until userInput = myName
End Sub
End Module
DotNetFiddle Live Demo
Functions
Description
Functions represent a block of code that will return a value.
Strictly speaking, you don't actually need to return a value from a function in VB.NET like you do in other programming languages. However, it is best practice to always return a value.
The following is an example for setting up a function:
Function MyFunction() As Integer
Dim someValue As Integer = 1
Return someValue
End Function
The code above defines a function named MyFunction and returns the value 1.
Return
The value to be returned will always come after the Return keyword.
The Return keyword can appear anywhere in the function, it can even appear multiple times in a function. However, once a Return gets executed, the function will not execute any code after it.
Here is an example of defining a function with multiple returns:
Function TimeOfDay() As String
Dim currentTime As DateTime = DateTime.Now
If (currentTime.Hour <= 11) Then
Return "Morning";
ElseIf (currentTime.Hour = 12) Then
Return "Noon"
ElseIf (currentTime.Hour <= 5) Then
Return "Afternoon"
ElseIf (currentTime.Hour <= 8) Then
Return "Evening"
End If
Return "Night"
End Function
It is worth mentioning that some coding conventions would prefer that you never use multiple return statements, i.e., the return will only ever happen once.
In that case, we can refactor the function above to be:
Function TimeOfDay() As String
Dim currentTime As DateTime = DateTime.Now
Dim returnValue As String = "Night"
If (currentTime.Hour <= 11) Then
returnValue = "Morning";
ElseIf (currentTime.Hour = 12) Then
returnValue = "Noon"
ElseIf (currentTime.Hour <= 5) Then
returnValue = "Afternoon"
ElseIf (currentTime.Hour <= 8) Then
returnValue = "Evening"
End If
Return returnValue
End Function
Both are functionally equivalent, they just use different coding conventions.
Sub Routines
Description
Sub Routines, often referred to as Subs, are simliar to functions in that they represent a block of code. The difference between the two is that subs do not return a value, instead subs will just execute the code.
You should have already seen sub routines. Don't remember it? Look inside the Module and you'll see that we have been using Sub Main all throughout these lessons.
The Main sub routine has a special purpose for the module of a Console Application that we will cover later.
Here is an example of defining a sub:
Sub MySub()
Console.WriteLine("Hello World!")
End Sub
The code above defines a sub routine named MySub and prints out the text "Hello World!" to the console.
Parameters
Description
Now that we've talked about Functions and Sub Routines, it's time to talk about how we actually give them information: parameters.
A parameter is a variable that lives in the parentheses of a Function or Sub. When you call the Function or Sub, you pass values into those parameters. Those values are called arguments.
In other words:
- Parameters are in the method's definition.
- Arguments are the actual values you pass in when you call it.
Example:
' name is the parameter
Sub Greet(name As String)
Console.WriteLine("Hello {0}!", name)
End Sub
Greet("David") ' "David" is the argument
Think of parameters as placeholders and arguments as the real data that fills those placeholders.
Defining Parameters
Parameters are defined inside the parentheses of your Function or Sub, just like variable declarations.
The syntax looks like this:
Sub MySub(parameterName As DataType)
' ...
End Sub
Function MyFunction(parameterName As DataType) As ReturnType
' ...
End Function
Here is an example that takes a number and prints whether it is positive or negative:
Sub PrintSign(number As Integer)
If (number > 0) Then
Console.WriteLine("{0} is positive", number)
ElseIf (number < 0) Then
Console.WriteLine("{0} is negative", number)
Else
Console.WriteLine("{0} is zero", number)
End If
End Sub
Public Sub Main()
PrintSign(5)
PrintSign(-10)
PrintSign(0)
End Sub
In this example, number is the parameter. Each time we call PrintSign, we pass a different argument into that parameter.
Multiple Parameters
You can have zero, one, or many parameters. If you have more than one, separate them with commas.
Sub PrintFullName(firstName As String, lastName As String)
Console.WriteLine("Full Name: {0} {1}", firstName, lastName)
End Sub
Function Add(leftValue As Integer, rightValue As Integer) As Integer
Return leftValue + rightValue
End Function
Public Sub Main()
PrintFullName("David", "Day")
Dim result As Integer = Add(10, 20)
Console.WriteLine("10 + 20 = {0}", result)
End Sub
Just like with variables, each parameter must have a unique name within the same Function or Sub.
ByVal and ByRef
In VB.NET, parameters can be passed in two ways:
- ByVal (by value) - a copy of the value is passed in.
- ByRef (by reference) - a reference to the original variable is passed in.
If you don't specify anything, then ByVal is the default.
ByVal
When you pass a parameter ByVal, the Function or Sub cannot change the original variable outside of the method.
Sub IncrementByVal(value As Integer)
value = value + 1
Console.WriteLine("Inside IncrementByVal: {0}", value)
End Sub
Public Sub Main()
Dim number As Integer = 10
IncrementByVal(number)
Console.WriteLine("After IncrementByVal: {0}", number)
End Sub
This will print something like:
Inside IncrementByVal: 11
After IncrementByVal: 10
The method changed its own copy of value, but the original number stayed the same.
ByRef
When you pass a parameter ByRef, the Function or Sub can change the original variable.
Sub IncrementByRef(ByRef value As Integer)
value = value + 1
Console.WriteLine("Inside IncrementByRef: {0}", value)
End Sub
Public Sub Main()
Dim number As Integer = 10
IncrementByRef(number)
Console.WriteLine("After IncrementByRef: {0}", number)
End Sub
This will print:
Inside IncrementByRef: 11
After IncrementByRef: 11
Use ByRef when the method should be allowed to modify the caller's variable. Otherwise, prefer ByVal.
Optional Parameters
Sometimes you want a parameter that the caller doesn't have to provide. In that case you can make the parameter optional by giving it a default value.
The rules are:
- Use the
Optionalkeyword. - You must provide a default value with
=. - Optional parameters must come after all required parameters.
Sub Greet(name As String, Optional greeting As String = "Hello")
Console.WriteLine("{0}, {1}!", greeting, name)
End Sub
Public Sub Main()
Greet("David") ' Hello, David!
Greet("David", "Bon matin") ' Bon matin, David!
End Sub
Optional parameters are great for "common case" values that you don't want to force the caller to type every time.
ParamArray (Variable Number of Arguments)
Sometimes you don't know how many values will be passed in. Instead of creating 50 million overloads, you can use ParamArray.
ParamArray lets you pass a variable number of arguments into a single method. Under the hood, it's treated as an array.
The rules:
- Use the ParamArray keyword.
- It must be the last parameter.
- Its type must be an array.
Sub PrintAll(ParamArray values() As Integer)
For Each value As Integer In values
Console.WriteLine(value)
Next
End Sub
Public Sub Main()
PrintAll(1)
PrintAll(10, 20, 30)
PrintAll(100, 200, 300, 400, 500, 600)
End Sub
In the example above, values behaves just like any other Integer array inside the method.
Named Arguments
VB.NET also lets you specify arguments by name instead of by order. This can improve readability, especially when you have a lot of parameters with similar data-types.
Sub LogMessage(message As String, severity As Integer, Optional category As String = "General")
Console.WriteLine("[{0}] ({1}) {2}", category, severity, message)
End Sub
Public Sub Main()
' positional arguments
LogMessage("Something happened.", 1, "System")
' named arguments
LogMessage(severity := 2, message := "Something else happened.", category := "Security")
' mix of both
LogMessage("Default category example", severity := 3)
End Sub
While you won't always need named arguments, they can make complex calls more self-documenting.
Exercise
Try to do the following:
- Create a Function named
AddThreeNumbersthat takes three Integer parameters and returns their sum. - Create a Sub named
PrintGreetingthat takes two String parameters: a name and a greeting message. Have it print the message and name to the console. - Modify
PrintGreetingso that the greeting message is an optional parameter with a default value of "Hello". - In
Main, call both methods several times with different arguments (try using named arguments at least once).
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
' test AddThreeNumbers
Dim sum1 As Integer = AddThreeNumbers(1, 2, 3)
Console.WriteLine("1 + 2 + 3 = {0}", sum1)
Dim sum2 As Integer = AddThreeNumbers(10, -5, 20)
Console.WriteLine("10 + (-5) + 20 = {0}", sum2)
Console.WriteLine("---")
' test PrintGreeting (positional)
PrintGreeting("David")
PrintGreeting("Alice", "Good morning")
Console.WriteLine("---")
' test PrintGreeting (named arguments)
PrintGreeting(name := "Bob", greeting := "Welcome")
End Sub
Function AddThreeNumbers(first As Integer, second As Integer, third As Integer) As Integer
Return first + second + third
End Function
Sub PrintGreeting(name As String, Optional greeting As String = "Hello")
Console.WriteLine("{0} {1}!", greeting, name)
End Sub
End Module
DotNetFiddle Live Demo
Scoping
Description
Up until now, the variables and methods you've created have all lived happily inside the same place. But as your programs grow, you need a way to control where something can be seen and who is allowed to use it.
This concept is called scoping or accessibility.
I find that it is best to illustrate the concept of scoping by providing a visual reference:
For example, if a variable is declared in the bottom-most slice of the pyramid (the largest slice) then it is accessible in all of the smaller slices, but if a variable is declared in the topmost slice of the pyramid (the smallest slice) then none of the other slices have access to the variable.
This is an example of Scoping inside the definitions:
Imports System
Public Module Module1
Dim moduleLevel As Integer = 0 ' moduleLevel is accessible anywhere in Module1
Public Sub Main()
Dim methodLevel As Int32 = moduleLevel + 1 'methodLevel is accessible only within Module1.Main
If moduleLevel >= 0 Then
Dim topmostLevel As Int32 = methodLevel + 1 ' topmostLevel is only accessible within this If statement
Console.WriteLine(moduleLevel)
Console.WriteLine(methodLevel)
Console.WriteLine(topmostLevel)
End If
End Sub
End Module
Access Modifiers
Access modifiers allow us to change the scope of a definition (like a Module, method, or variable).
In VB.NET, the two most common modifiers are:
- Public
- Private
There are more advanced ones, like Protected and Friend, but for now, we'll keep it simple.
Private Modifier
The Private access modifier will flag the definition as only being accessible inside the class, module, or structure where it was defined.
In other words, if you mark something as Private, you're saying: This belongs to me and nobody else can touch it.
Example:
Module Module1
Private secretValue As Integer = 42
Sub ShowSecret()
Console.WriteLine(secretValue) ' allowed
End Sub
End Module
Module Module2
Sub ShowSecret()
Console.WriteLine(Module1.secretValue) ' not allowed because it is private
End Sub
End Module
Trying to access secretValue from Module2 will result in a compilation error because it's out of scope.
Public Modifier
Public is the opposite of Private. It will flag the definition as being accessible anywhere throughout the project.
If you want something to be available everywhere, you mark it as Public.
Example:
Module Module1
Public secretValue As Integer = 42
Sub ShowSecret()
Console.WriteLine(secretValue) ' allowed
End Sub
End Module
Module Module2
Sub ShowSecret()
Console.WriteLine(Module1.secretValue) ' allowed because it is public
End Sub
End Module
Why Does Scope Matter?
- You don't want other parts of your program accidentally modifying internal values.
- You want to hide complexity and expose only what the user needs.
- You want to avoid naming conflicts and unpredictable bugs.
Private values help protect your logic while public values help organize what your program exposes.
Additional Information
Please visit the official documentation on access levels for more information on scoping.
The documentation will be able to provide you with every access modifier.
Converting Data
ToString Method
Every single object and data-type contains a ToString method. This method will print out the String representation of the object's value.
Sometimes the result of the ToString method is exactly what you would expect; othertimes, it is not.
The following is an example of using the ToString method:
Dim integerValue As Integer = 1
Console.Write("Integer Conversion: ")
Console.WriteLine(integerValue.ToString()) ' 1
Dim fractionalValue As Double = 1.5
Console.Write("Fractional Conversion: ")
Console.WriteLine(fractionalValue.ToString()) ' 1.5
Dim booleanValue As Boolean = True
Console.Write("Boolean Conversion: ")
Console.WriteLine(booleanValue.ToString()) ' True
Dim dateValue As DateTime = DateTime.Now
Console.Write("Date Conversion: ")
Console.WriteLine(dateValue.ToString()) ' current date/time in the default culture format of the operating system
Formatting
The ToString method accepts a couple of parameters that allow you to format the returned String. Documentation here: https://docs.microsoft.com/en-us/dotnet/standard/base-types/formatting-types
Depending on the data-type, the format parameter may behave differently. The list below contains important documentation that you should reference when formatting Strings:
- Custom Date and Time Formats: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
- Custom Numeric Formats: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings
The following is an example of converting a Date value to a String in several different formats:
Dim date1 As DateTime = DateTime.Now
Dim formats() As String = { "MMMM dd, yyyy", "MM-dd-yyyy", "yy/MM/dd", "hh:mm:ss", "MM/dd/yyyy h:m" }
For Each format As String In formats
Console.WriteLine("{0}: {1}", format, date1.ToString(format))
Next
The following is an example of converting a numeric value to a String in several different formats:
Dim number1 As Double = 1523775.123456789
Dim formats() As String = { "C", "N3", "N0", "##,#" }
For Each format As String In formats
Console.WriteLine("{0}: {1}", format, number1.ToString(format))
Next
Exercise
Try to do the following:
- Create a numeric or date value and give it an arbitrary value
- Prompt the user for a format
- Print the formatted String of the variable based on the user's input
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim number1 As Double = 1523775.123456789
Console.Write("Numeric Format: ")
Dim format As String = Console.ReadLine()
Console.WriteLine("{0} formatted: {1}", number1, number1.ToString(format))
End Sub
End Module
DotNetFiddle Live Demo
Convert Method
Description
The Convert method is fairly straightforward, you pass it an argument and then it tries to convert it to the desired data-type.
The following table holds the various data-types and their specific Convert method:
Naming Convention
You may have noticed that some of the data-types' method has the same name as the type itself, like SByte has Convert.ToSByte. Some of the others use a different name entirely, like ULong has Convert.ToUInt64. This is because Convert methods use the CLR naming convention.
VB.NET and C#, while different languages with completely different syntax, both ultimately get compiled down to the same language. The CLR names are sort of the "bridge" between both languages.
You can use whichever you prefer, e.g. Integer or Int32:
Dim vbName As Integer
Dim clrName As Int32
Both of the variables in the above code will do the same thing. The important thing is that you stick with a consistent naming convention throughout the entire project.
Example
The following is an example of converting a String value into several of the data-types:
Dim string1 As String = "1"
Dim boolean1 As Boolean = Convert.ToBoolean(string1)
Dim integer1 As Integer = Convert.ToInt32(string1)
Dim double1 As Double = Convert.ToDouble(string1)
Dim byte1 As Byte = Convert.ToByte(string1)
Exception
If you try to convert a value that cannot be converted (e.g., text to number), then an error will be thrown at runtime called a FormatException: Documentation here: https://docs.microsoft.com/en-us/dotnet/api/system.formatexception
For example:
Dim string1 As String = "Hello World"
Dim integer1 As Integer = Convert.ToInt32(string1)
The Convert method should only be used when you are absolutely certain that the data being converted is the expected data-type.
Exercise
Try to do the following:
- Prompt the user enter enter a Decimal.
- Convert the String returned from Console.ReadLine to a Decimal.
- Print the number back as a currency string.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Console.Write("Value: ")
Dim userInput As String = Console.ReadLine()
Dim convertedInput As Decimal = Convert.ToDecimal(userInput)
Dim decimalAsCurrency As String = convertedInput.ToString("c")
Console.WriteLine("Currency: {0}", decimalAsCurrency)
End Sub
End Module
DotNetFiddle Live Demo
TryParse Method
Description
The TryParse method is by far the safest way to convert a value. The way it works is by taking a String and a ByRef variable as arguments, then returns a Boolean based on if the conversion was successful.
The following table holds the various data-types and their specific TryParse method:
Unlike the Convert method, the TryParse method has both the CLR name as well as the VB equivalent name.
Example
The following is an example of converting a String to an Integer based on user input:
Dim string1 As String = Console.ReadLine()
Dim integer1 As Integer
If (Integer.TryParse(string1, integer1)) Then
Console.WriteLine("Successful!")
Else
Console.WriteLine("Failed.")
End If
Exercise
Try to do the following:
- Prompt the user to enter enter a Decimal.
- Convert the String returned from Console.ReadLine to a Decimal using TryParse.
- Use a Do loop to force the user to enter a valid Decimal.
- Format the Decimal to its currency value equivalent.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Console.Write("Decimal: ")
Dim input As String = Console.ReadLine()
Dim conversion As Decimal
Do Until Decimal.TryParse(input, conversion)
Console.WriteLine("Invalid input, please enter a valid decimal.")
Console.Write("Decimal: ")
input = Console.ReadLine()
Loop
Console.WriteLine("Conversion: {0}", conversion.ToString("C"))
End Sub
End Module
DotNetFiddle Live Demo
Classes
Description
So far, you've been writing code using Modules, Functions, Subs, and variables. These are great for small programs, but sooner or later you'll want your program to grow. It might be to handle more data, model real-world things, or organize logic more cleanly. That's where classes come in.
A class is the backbone of Object-Oriented Programming (aka OOP). A class describes something your program needs to work with, like such as a player, a product, a book, a button, etc.
From your class definition, your program can create actual objects (also called "instances"). The class describes what an object is and what it can do; the object is the actual thing you use in your program.
Real-World Analogy
Think of a class like an architect's blueprint for a house. It defines:
- What rooms the house has
- Where the doors and windows go
- How everything fits together
But the blueprint is not a house. To get a real house you can live in, you must build one using the blueprint.
Likewise:
- A class is the blueprint.
- An object created from the class is the actual "house."
Why Use Classes?
Classes help you:
- Organize your code by grouping related data and behavior together.
- Model real-life things in your program.
- Reuse code without rewriting the same logic over and over.
Once you understand classes, you'll be able to build much larger and more powerful programs with fewer bugs.
A Simple Class Example
Here is an extremely simple example of defining a class:
Public Class Cat
Public Property Name As String
Public Property Birthday As DateTime
Public Property FurColor As String
Public Property EyeColor As String
End Class
And here's how you create and use an object from that class:
Module Program
Sub Main()
Dim minou As New Person()
minou.Name = "Stella Belle"
minou.Birthday = New DateTime(2011, 8, 1)
minou.FurColor = "Gray"
minou.EyeColor = "Gold"
Console.WriteLine("{0}, the {1} cat has {2} eyes.", minou.Name, minou.FurColor, minou.EyeColor)
End Sub
End Module
In this example:
Catis the class (the blueprint).minouis an object (an actual instance).Name,Birthday,FurColor, andEyeColorare the data that the object holds.
Classes vs. Modules
At first, Classes and Modules may look similar in that they both contain code. But they serve different purposes:
| Modules | Classes |
|---|---|
| Contain shared code and functions | Define objects you can create |
| Cannot be instantiated | Can create many instances |
| Good for utility or "global" code | Good for representing things and data |
| All members are implicitly shared | Each object has its own data |
Modules are great for tools. Classes are great for objects.
The reason why Console Applications are Modules in VB.NET is mainly a holdover from legacy versions of Visual Basic (like VB6). In C#, the C-equivalent of VB.NET, a Console Applications is actually a class.
What Classes Can Contain
As you go through this chapter, you'll learn that a class can have:
- Properties: data that belongs to the object
- Methods: actions the object can take
- Events: notifications the object can raise
- Constructors: code that runs when an object is created
- Inheritance: ways for one class to build on another
Each of these topics will be covered in its own lesson.
Properties
Description
A property is essentially a variable defined on the class that represents data that belongs to the object.
A good way to think of properties is to think of the characteristics of the thing you're trying to represent.
For example, if I were creating a class to represent a cup, I might have the following properties defined:
- Volume (double representing the amount of liquid it can hold)
- Material (string representing the material the cup is made up of)
- Color (string representing the cup's color)
- HasHandle (boolean indicating if the cup has a handle)
Long Form Properties
The following is an example of defining a property using the "long form" syntax:
Private _myProperty As String ' backing field (actual data)
Public Property MyProperty As String ' property exposed publically
Get
Return _myProperty ' read
End Get
Set(value As String)
_myProperty = value ' write
End Set
End Property
What this does is create a private variable, scoped to the class and then the property has a getter and setter to return/set the value of the private variable.
Keep in mind that VB.NET is not a case-sensitive language, meaning that these two variable names are actually the same:
Dim myProperty As String
Dim MyProperty As String
This is why in the example above, I prefixed the private variable with an underscore. This is a very common coding convention to prevent name conflicts.
You may be wondering, why not just make the private variable public? Long form properties are useful when you need business logic as the value is set.
For example:
Private _age As Integer
Public Property Age As Integer
Get
Return _age
End Get
Set(value As Integer)
If value < 0 Then
Throw New ArgumentException("Age cannot be negative.")
End If
_age = value
End Set
End Property
Auto-Implemented Properties
Starting in VB.NET version 10 (roughly around 2015), syntactic sugar was added to properties to eliminate much of the boilerplate.
We can simply define a property inline without the private variable or getter/setters, and VB.NET will implicitly do that for us behind the scenes.
This is an example of simplifying the long form property example from above using the auto-implemented property syntax:
Public Property MyProperty As String
The long form property syntax still has its use, but 9 times out of 10 you can go ahead and use auto-implemented properties.
Example
This is an example of creating a class, defining a few properties, and instantiating an object:
Imports System
Public Module Module1
Public Sub Main()
Dim class1 As New MyClass
class1.Property1 = "Hello World!"
Console.WriteLine("The value of class1.Property1 is: {0}", class1.Property1)
End Sub
End Module
Public Class MyClass
Public Property Property1 As String
End Class
Exercise
Try to do the following:
- Create a Class to represent a desk.
- Create the following properties:
- Number of Drawers
- Construction Type
- Color
- Height
- Width
- Length
- Cost
- Create a new instance of the Class, specifying the property values.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim desk1 As New Desk
desk1.DrawerCount = 4
desk1.Construction = "Wood"
desk1.Color = "White Ash"
desk1.Height = 44.5
desk1.Width = 38
desk1.Length = 24.5
desk1.Cost = 199.99
End Sub
End Module
Public Class Desk
Public Property DrawerCount As Integer
Public Property Construction As String
Public Property Color As String
Public Property Height As Double ' measured in inches
Public Property Width As Double ' measured in inches
Public Property Length As Double ' measured in inches
Public Property Cost As Decimal
End Class
DotNetFiddle Live Demo
Events
Description
An event is a way for a class to signal that something has happened. Other parts of your program can then respond when that event occurs.
If properties represent an object's data and methods represent what an object can do, then events represent something that has occurred inside the object.
VB.NET can be an event-driven programming language, although you will see it more often in Windows Form Applications than you will in Console Applications.
Here are some examples of events:
- A download object raises a "Completed" event when the download finishes.
- A timer object raises a "Tick" event at a given interval.
- A person object raises a "Birthday" event when the current day matches the person's birthday.
The class raising the event doesn't actually know who is listening to it and that's the entire point. Think of events as "notifications" to whatever is listening.
Declaring Events
Declaring an event on a class is straightforward. You simply use the Event keyword.
For example:
Public Class Timer
Public Event Tick()
End Class
The code above declares an event named Tick, but nothing happens yet. It's simply the definition of a signal the class may raise.
Raising Events
Events are raised using the RaiseEvent keyword. This is typically done inside a method:
Public Class Counter
Private _value As Integer
Public Sub Add(amount As Integer)
_value += amount
If (_value >= 10) Then
RaiseEvent ThresholdReached()
End If
End Sub
Public Event ThresholdReached()
End Class
In the example above, when the internal value reaches 10 or more, the class raises the ThresholdReached event to notify any listeners.
Another, more common example, is to raise an event when a property's value changes:
Public Class Person
Private _name As String
Public Property Name As String
Get
Return _name
End Get
Set(value As String)
If (value <> _name) Then
OnNameChanged(EventArgs.Empty)
End If
_name = value
End Set
End Property
Protected Overridable Sub OnNameChanged(e As EventArgs)
RaiseEvent NameChanged(Me, e)
End Sub
Public Event NameChanged(sender As Object, e As EventArgs)
End Class
This pattern is very common and if you look into many of the .NET class definitions, you will find that they follow a very similar pattern.
This is a bit advanced, but I wanted to give you a preview of it now.
Subscribing To An Event
Other code can listen to an event using the AddHandler keyword. This connects an event to a method, called the event handler.
For example:
Dim counter As New Counter()
AddHandler counter.ThresholdReached, AddressOf OnThresholdReached
Sub OnThresholdReached()
Console.WriteLine("The threshold was reached!")
End Sub
When the event is raised, the method you provided is automatically called.
Think of it like subscribing to a newsletter: the moment something happens, you receive the notification.
Removing an Event Handler
If you no longer want to receive notifications, you can unsubscribe using the RemoveHandler keyword:
RemoveHandler counter.ThresholdReached, AddressOf OnThresholdReached
This is not always necessary in console programs, but it is important in long-running applications (like Windows Form Applications or services) to prevent memory leaks.
Exercise
Try to do the following:
- Create a Class to represent a desk
- Create a property to represent the desk's price
- Create an event that gets invoked when the price changes
- Create a new instance of the desk
- Prompt the user to change the value of the price
- Loop until the user enters a valid value
- Change the value of the price
- Display the new price to the user
Solution
Show Exercise Code
Imports System
Public Module Module1
Private desk1 As New Desk
Public Sub Main()
AddHandler desk1.PriceChanged, AddressOf DeskPriceChanged
Console.Write("Price: ")
Dim input As String = Console.ReadLine()
Do Until Decimal.TryParse(input, desk1.Price)
Console.WriteLine("Invalid input, please enter a valid decimal.")
Console.Write("Price: ")
input = Console.ReadLine()
Loop
End Sub
Sub DeskPriceChanged(sender As Object, e As EventArgs)
Console.WriteLine("The price has changed, it is now: {0}", desk1.Price)
End Sub
End Module
Public Class Desk
Private _price As Decimal
Public Property Price As Decimal
Get
Return _price
End Get
Set(value As Decimal)
If (_price <> value) Then
_price = value
RaiseEvent PriceChanged(Me, EventArgs.Empty)
End If
End Set
End Property
Public Event PriceChanged(sender As Object, e As EventArgs)
End Class
DotNetFiddle Live Demo
Constructor
Description
The Class's constructor is a special Sub, always named New, that is executed when a new instance of the Class is created. However, the constructor is not required when defining a class.
It is very important to know that the code inside of the constructor will always execute before any other code in the Class will.
Here is an example of creating a constructor:
Public Class SomeClass
Public Sub New()
' this is the constructor
End Sub
End Class
If a constructor is not defined, an empty one will be created for you behind the scenes. This constructor is called the default constructor.
Constructors are useful because they can be used to set default values of properties within the Class as well as run "startup" code when the new instance of the class is created.
Multiple Constructors
Because constructors are essentially just Sub routines that get executed when an instance of the class is created, it is possible to pass one or more parameters to the constructor.
It is also possible to have multiple constructors with different parameters, that is to say that they have multiple signatures. This is called constructor overloading. The important thing is a Class cannot have multiple constructors with the same signature.
The following is an example defining a Class with multiple signatures:
Public Class SomeClass
Public Property SomeProperty As Boolean
Public Sub New()
' called when doing: Dim foo As New SomeClass()
SomeProperty = True
End Sub
Public Sub New(value As Boolean)
' called when doing: Dim foo As New SomeClass(True) -or- Dim bar As New SomeClass(False)
SomeProperty = value
End Sub
End Class
Exercise
Try to do the following:
- Create a Class to represent a cup.
- Create the following properties:
- Volume
- Material
- Create two constructors:
- Parameterless constructor that sets the default value of the properties.
- Constructor with two parameters that set the value of the properties.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim defaultCup As New Cup()
Dim customCup As New Cup(6.7, "Glass")
Console.WriteLine("defaultCup: {0}, {1}", defaultCup.Volume, defaultCup.Material)
Console.WriteLine("customCup: {0}, {1}", customCup.Volume, customCup.Material)
End Sub
End Module
Public Class Cup
Public Property Volume As Double
Public Property Material As String
Public Sub New()
Me.New(64, "Ceramic")
End Sub
Public Sub New(volumeValue As Double, materialValue As String)
Volume = volumeValue
Material = materialValue
End Sub
End Class
DotNetFiddle Live Demo
Inheritance
Description
Inheritance is one of the most powerful features of object-oriented programming. It allows you to create a new Class that reuses, extends, or modifies the behavior of an existing Class.
When one Class inherits from another, the original Class is called the base Class (or "parent"), and the new Class is called the derived Class (or "child").
The derived Class automatically receives:
- All Public and Protected properties
- All Public and Protected methods
- Any events defined on the base Class
This eliminates duplication and helps organize related Classes into hierarchies.
Real-World Analogy
Imagine you creat a Class named Territory. All territories have things in common:
- They have a name.
- They have a population.
- They have a time zone.
From this base Class, you create specific territories: state, county, city, etc.
Each one inherits the common behavior of a territory, but can also add its own features.
To create a derived class, use the Inherits keyword after the class's name. For example:
Public Class Territory
Public Property Name As String
Public Property Population As UInteger
Public Property TimeZone As String
End Class
Public Class State
Inherits Territory
Public Property Capital As City
End Class
Public Class County
Inherits Territory
Public Property State As State
Public Function IsParish() As Boolean
Return State.Name = "Louisiana"
End Function
End Class
Public Class City
Inherits Territory
Public Property County As County
End Class
With this setup, State, County, and City will all have the properties defined on the Territory class as well as the properties/methods defined inside of them.
Overriding Base Class Methods
Sometimes the derived Class needs to change or customize behavior from the base Class. This is called overriding.
First, the base Class must mark the member as Overridable:
Public Class Animal
Public Overridable Sub Speak()
Console.WriteLine("The animal makes a sound.")
End Sub
End Class
Then the derived Class can override it:
Public Class Dog
Inherits Animal
Public Overrides Sub Speak()
Console.WriteLine("Bark!")
End Sub
End Class
Now, calling the Speak method on a Dog object will use the overridden version.
MyBase
If you override a method but still want to call the original version, you can use the MyBase keyword.
For Example:
Public Class MeanDog
Inherits Dog
Public Overrides Sub Speak()
MyBase.Speak() ' calls Dog.Speak because MeanDog inherits Dog
Console.WriteLine("Grrrrr.")
End Sub
End Class
This is optional, but useful when extending behavior rather than replacing it entirely.
Exercise
Try to do the following:
- Create a base Class named Vehicle with:
- A Make property
- A Model property
- A method named Describe that prints the make and model
- Create a derived Class named Car that:
- Inherits from Vehicle
- Has an additional property named Doors
- Override the Describe method in Car to include the number of doors.
- In your Main method, create a Car object, set its properties, and call Describe.
Solution
Show Exercise Code
Imports System
Public Module Module1
Public Sub Main()
Dim car As New Car()
car.Make = "Toyota"
car.Model = "Corolla"
car.Doors = 4
car.Describe()
End Sub
End Module
Public Class Vehicle
Public Property Make As String
Public Property Model As String
Public Overridable Sub Describe()
Console.WriteLine("{0} {1}", Make, Model)
End Sub
End Class
Public Class Car
Inherits Vehicle
Public Property Doors As Integer
Public Overrides Sub Describe()
Console.WriteLine("{0} {1} with {2} doors", Make, Model, Doors)
End Sub
End Class
DotNetFiddle Live Demo
LINQ
Description
VB.NET implemented a robust way to query collections through component called Language Integrated Query, aka LINQ (pronounced like "link").
LINQ is expressive in how the queries are built, which has the advantage that even people with no programming experience can have a pretty good understanding of what a LINQ statement is doing.
There are two different flavors of syntax in how LINQ can be implemented:
- Method Syntax
- Query Syntax
In the following lessons I will be using the query syntax almost exclusively. This is not to say that the method syntax is wrong in any way, but as the author I feel you would benefit more from learning the query syntax in case you decide to learn a query language in the future like SQL.
Namespace
In order to use LINQ, you will need to import the System.Linq namesapce. Documentation here: https://docs.microsoft.com/en-us/dotnet/api/system.linq
By running a LINQ query, the result will almost always be an IEnumerable class, which means that you will also need to import the System.Collections.Generic namespace like back in the Lists lesson.
Aggregates
Description
Numeric collections can be easily aggregated by using one of the following methods:
- Average
- Max
- Min
- Sum
Average
The Average LINQ method returns the average of a collection.
This is an example of using the Average method:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim average As Double = collection.Average()
Functionally, this is the same as doing it yourself:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim sum As Integer = 0
For Each item As Integer In collection
sum = sum + item
Next
Dim average As Double = sum / collection.length
Max
The Max LINQ method returns the highest value from a collection.
This is an example of using the Max method:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim max As Integer = collection.Max()
Functionally, this is the same as doing it yourself:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim max As Integer = collection(0)
For Each item As Integer In collection
If (max < item) Then
max = item
End If
Next
Min
The Min LINQ method returns the lowest value from a collection.
This is an example of using the Min method:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim min As Integer = collection.Min()
Functionally, this is the same as doing it yourself:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim min As Integer = collection(0)
For Each item As Integer In collection
If (min > item) Then
min = item
End If
Next
Sum
The Sum LINQ method returns the sum total of a collection.
This is an example of using the Sum method:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim sum As Double = collection.Sum()
Functionally, this is the same as doing it yourself:
Dim collection() As Integer = { 1, 2, 3, 4, 5 }
Dim sum As Integer = 0
For Each item As Integer In collection
sum = sum + item
Next
Exercise
Try to do the following:
- Prompt the user to enter 5 numeric values
- Validate that the entered values are the correct data-type
- Perform the Average, Max, Min, and Sum methods on the collection and print the results
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Module Module1
Public Sub Main()
Dim collection As New List(Of Integer)
For index As Integer = 1 To 5
collection.Add(PromptAndValidateInteger(index))
Next
Console.WriteLine()
Console.WriteLine("Average: {0}", collection.Average())
Console.WriteLine("Max: {0}", collection.Max())
Console.WriteLine("Min: {0}", collection.Min())
Console.WriteLine("Sum: {0}", collection.Sum())
End Sub
Private Function PromptAndValidateInteger(index As Integer) As Integer
Console.Write("Decimal {0}: ", index)
Dim input As String = Console.ReadLine()
Dim conversion As Decimal
Do Until Decimal.TryParse(input, conversion)
Console.WriteLine("Invalid input, please enter a valid decimal.")
Console.Write("Decimal {0}: ", index)
input = Console.ReadLine()
Loop
return conversion
End Function
End Module
DotNetFiddle Live Demo
Select
Description
The Select clause allows for you to select one or more properties from a collection of objects. Documentation here: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/queries/select-clause
A practical example of applying a select clause would be if you had Class that contained several properties, but you wanted a separate collection that only contained the values of a specific property.
Example
For example, assume that we have the following class:
Public Class Person
Public Property Name As String
Public Property Birthday As Date
Public Sub New(nameValue As String, birthdayDate As Date)
Name = nameValue
Birthday = birthdayDate
End Sub
End Class
Now lets assume that you have a collection of several people, but you only want to get everybody's name. This can be doing using:
Dim people() As Person = {
New Person("John Richard", New Date(1970, 1, 1)),
New Person("Marie Thibodeaux", New Date(1990, 12, 25)),
New Person("Dylan Doucet", New Date(1998, 8, 12))
}
Dim names As IEnumerable(Of String) = From individual As Person In People
Select individual.Name
What Select Actually Does
The Select clause does not modify the original collection. Instead, it creates a new collection based on what you specify. In other words, Select is a transformation operator.
You can think of it like mapping each item in the collection into a new form. This new form can be:
- A single property
- Multiple properties
- A new anonymous object
- A new instance of a class
- A calculated value
The type you return determines the type of the resulting collection.
Exercise
Try to do the following:
- Create a Class named Book with the following properties:
- Title
- Author
- PageCount
- Create a collection of several Book objects.
- Use a LINQ Select to get only the titles from the collection.
- Print the results to the console.
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Module Module1
Public Sub Main()
Dim books = {
New Book("1984", "George Orwell", 328),
New Book("Brave New World", "Aldous Huxley", 268),
New Book("Harry Potter And The Prisoner Of Azkaban", "J.K. Rowling", 435)
}
Dim titles = From b In books
Select b.Title
Console.WriteLine("Titles:")
For Each title In titles
Console.WriteLine("* {0}", title)
Next
End Sub
End Module
Public Class Book
Public Property Title As String
Public Property Author As String
Public Property PageCount As Integer
Public Sub New(titleValue As String, authorValue As String, pages As Integer)
Title = titleValue
Author = authorValue
PageCount = pages
End Sub
End Class
DotNetFiddle Live Demo
Where
Description
The Where clause allows you to filter a collection based on one or more conditions. Only the items that match the condition(s) will be returned.
If the Select clause answers the question "What information do I want?" then the Where clause answers the question "Which items do I want?"
Documentation can be found: https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/queries/where-clause
Example
For example, assume that we have the following class:
Public Class Person
Public Property Name As String
Public Property Birthday As Date
Public Sub New(nameValue As String, birthdayDate As Date)
Name = nameValue
Birthday = birthdayDate
End Sub
End Class
Now lets assume that you have a collection of several people, but you only want to get people born before 1995. This can be doing using:
Dim people() As Person = {
New Person("John Richard", New Date(1970, 1, 1)),
New Person("Marie Thibodeaux", New Date(1990, 12, 25)),
New Person("Dylan Doucet", New Date(1998, 8, 12))
}
Dim oldies As IEnumerable(Of String) = From individual As Person In People
Where individual.Birthday.Year <= 1995
Select individual
The results of "oldies" will only contain Person records for John and Marie.
Multiple Conditions
You can combine multiple comparisons using logical operators discussed in the Operators Lesson.
Using the same example above, we can get people who were born before August of 1990:
Dim oldies As IEnumerable(Of String) = From individual As Person In People
Where individual.Birthday.Year <= 1990
AndAlso individual.Birthday.Month < 8
Select individual
The results of "oldies" will only contain Person records for John.
Combining Where And Select
In the previous examples we return the entire object, but we could combine both the Where and Select clause to filter and transform the data.
For example, this will return the names of everyone born after January of 1990:
Dim youngieNames As IEnumerable(Of String) = From individual As Person In People
Where individual.Birthday.Year >= 1990
AndAlso individual.Birthday.Month >= 1
Select individual.Name
Exercise
Try to do the following:
- Create a Class named Book with the following properties:
- Title
- Author
- PageCount
- Use a Where clause to filter books that have more than 300 pages.
- Use a Select clause to select only the titles of the filtered books.
Solution
Show Exercise Code
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Module Module1
Public Sub Main()
Dim books = {
New Book("1984", "George Orwell", 328),
New Book("Brave New World", "Aldous Huxley", 268),
New Book("Harry Potter And The Prisoner Of Azkaban", "J.K. Rowling", 435),
New Book("A Book", "A.N. Author", 199)
}
Dim filteredBookTitles = From book In books
Where book.PageCount > 300
Select book.Title
Console.WriteLine("Titles:")
For Each title In filteredBookTitles
Console.WriteLine("* {0}", title)
Next
End Sub
End Module
Public Class Book
Public Property Title As String
Public Property Author As String
Public Property PageCount As Integer
Public Sub New(titleValue As String, authorValue As String, pages As Integer)
Title = titleValue
Author = authorValue
PageCount = pages
End Sub
End Class
DotNetFiddle Live Demo
Order By
Description
By now we know that the Where clause will filter data and the Select clause will transform data. Now it's time to sort the data.
The Order By and Order By Descending clauses will sort the data, the former from smallest to largest and the latter just the opposite.
Documentation can be found: https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/queries/order-by-clause
Example
For example, assume that we have the following class:
Public Class Person
Public Property Name As String
Public Property Birthday As Date
Public Sub New(nameValue As String, birthdayDate As Date)
Name = nameValue
Birthday = birthdayDate
End Sub
End Class
Now lets assume that you have a collection of several people, but you wanted to sort them by their Birthday. This can be doing using:
Dim people() As Person = {
New Person("Marie Thibodeaux", New Date(1990, 12, 25)),
New Person("John Richard", New Date(1970, 1, 1)),
New Person("Dylan Doucet", New Date(1998, 8, 12))
}
Dim sorted As IEnumerable(Of String) = From individual As Person In People
Order By individual.Birthday
Select individual
The results of "sorted" will only every record but it will be in the order of John, Marie, and then Dylan.
We can specify that we want the sort reversed by using the Descending keyword:
Dim sorted As IEnumerable(Of String) = From individual As Person In People
Order By individual.Birthday Descending
Select individual
Combining The LINQ Methods
Putting it all together, here is an example of filtering, transforming, and ordering a collection:
Dim youngieNames As IEnumerable(Of String) = From individual As Person In People
Where individual.Birthday.Year >= 1990
AndAlso individual.Birthday.Month >= 1
Order By individual.Birthday
Select individual.Name
Exercise
It feels sort of pointless to give you another exercise because you would literally be taking the solution from the previous lesson and adding one extra line.
I'm not going to do that to you.
Congratulations!
First off, I would like to say congratulations on completing every lesson. By this point you should have developed solid fundamentals that will make you a successfull programmer.
Now comes the big question: what should you do next? I would highly recommend building a project. Here are some project ideas:
- Pokédex - Create a class to represent a Pokémon and allow users to search for pokémon by their name or id.
- CRUD - Create a class to store a person and then allow users to create, read, update, and delete people.
- Tic-Tac-Toe - Using ASCII art to "draw" on the console, build a player versus computer tic-tac-toe game.
- Calculator - Calculators can be as simple or robust as possible, try building a calculator that supports pi as well as clear entry and clear global functions.
Remember, programming is a "use it or lose it" skill. If you do not keep programming, as time goes by you will start to lose your edge. Whatever you decide to do going forward, I encourage you to continue programming and nevery shy away from asking for help.
In closing, if you are looking for a community to join full of nerds like myself, come on over to https://www.vbforums.com. I go by the handle dday9 and I hope to see you soon!