Site logo

VbLessons

Teaching VB.NET, the right way.

Navigation

Lessons

Chapter 1. The Basics
  1. Creating A New Project
  2. Option Strict
  3. Variables
  4. Input And Output
  5. Arithmetic
  6. Comments

Chapter 2. Logic
  1. If/Then Statements
  2. Select/Case
  3. Ternary If
  4. Operators

Chapter 3. Collections
  1. Arrays
  2. Lists
  3. Dictionaries

Chapter 4. Loops
  1. For/Next Loop
  2. For/Each Loop
  3. Do Loop

Chapter 5. Methods
  1. Functions
  2. Sub Routines
  3. Parameters
  4. Scoping

Chapter 6. Converting Data
  1. ToString Method
  2. Convert Method
  3. TryParse Method

Chapter 7. Classes
  1. Classes
  2. Properties
  3. Events
  4. Constructor
  5. Inheritance

Chapter 8. Language Integrated Query
  1. LINQ
  2. Aggregates
  3. Select
  4. Where
  5. Order By

Chapter 9. Conclusion
  1. Conclusion

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:

  1. Create a new fiddle
  2. Optionally change the target language to VB.NET
  3. Optionally change the project type to console
Screenshot of DotNetFiddle targetting Visual Basic .NET.

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:

  1. Create a new project using either:
    • The shortcut key Ctrl + Shift + n.
    • Selecting File > New > Project from the menu.
  2. Optionally change the language to Visual Basic.
  3. Optionally change the platform to Windows.
  4. Optionally change the project type to Console.
  5. Select Console Application (.NET Framework).
  6. Click on the Next button.
  7. Optionally configure your project by changing the project's name, location, etc.
  8. Click on the Create button.
Screenshot of a Visual Basic .NET console application in Visual Studio 2019.

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:

  1. Expand the Project menu
  2. Click on the project's properties menu item (last item)
  3. Click on the Compile tab
  4. Change the Option Strict dropdown to be On
  5. 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:

  1. Expand the Tools menu
  2. Click on the Options menu item
  3. Expand the Projects and Solutions tree node
  4. Select the VB Defaults option
  5. Change the Option Strict dropdown to be On
Screenshot of default project settings in in Visual Studio 2019 with Option Strict turned 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:

Documentation: https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/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:

  1. Prompt the user for their name.
  2. Store the user input in a variable.
  3. 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:

Documentation: https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/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:

  1. Calculate the Pythagorean Theorem (wiki)
  2. Calculate the value of speed using Galileo's formula (wiki)

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:

  1. Prompt for the user's first name.
  2. Check if it matches your name.
  3. Check if it matches somebody elses name
  4. 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:

  1. Imagine you are giving the user a test.
  2. You ask them 10 questions.
  3. At the end of the test, get their perecentage.
  4. 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:

  1. Imagine you are giving the user a test.
  2. You ask them 10 questions.
  3. 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:

Documentation: https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/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:

Documentation: https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/logical-and-bitwise-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:

  1. Create an array to store all the letters in the English alphabet
  2. 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:

  1. Create a List that represents a parking garage full of vehicles.
  2. Initialize the List with several vehicles.
  3. 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:

  1. Create a Dictionary that represents a restaurant menu.
  2. Initialize the List with several menu items.
  3. Prompt the user for what item they want to buy.
  4. Give the user readable error if they ask for an item that is not in the dictionary.
  5. 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:

Loop number 1 Loop number 2 Loop number 3 Loop number 4 Loop number 5 Loop number 6 Loop number 7 Loop number 8 Loop number 9 Loop number 10

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:

  1. Create an Array that holds the alphabet.
  2. Create a List that holds characters.
  3. 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:

  1. Create an Array that holds the several numbers.
  2. Create a variable that will store the sum of all the numbers.
  3. Loop over the array and add each number to the variable.
  4. 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:

  1. 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 Optional keyword.
  • 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:

  1. Create a Function named AddThreeNumbers that takes three Integer parameters and returns their sum.
  2. Create a Sub named PrintGreeting that takes two String parameters: a name and a greeting message. Have it print the message and name to the console.
  3. Modify PrintGreeting so that the greeting message is an optional parameter with a default value of "Hello".
  4. 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:

Scoping pyramid showing loops and if/thens as the smallest scope, method being a larger scope, and module being the largest scope.

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:

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:

  1. Create a numeric or date value and give it an arbitrary value
  2. Prompt the user for a format
  3. 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:

Data-Type Method Documentation
Boolean Convert.ToBoolean https://docs.microsoft.com/en-us/dotnet/api/system.convert.toboolean
Byte Convert.ToByte https://docs.microsoft.com/en-us/dotnet/api/system.convert.tobyte
Char Convert.ToChar https://docs.microsoft.com/en-us/dotnet/api/system.convert.tochar
DateTime Convert.ToDateTime https://docs.microsoft.com/en-us/dotnet/api/system.convert.todatetime
Decimal Convert.ToDecimal https://docs.microsoft.com/en-us/dotnet/api/system.convert.todecimal
Double Convert.ToDouble https://docs.microsoft.com/en-us/dotnet/api/system.convert.todouble
Integer Convert.ToInt32 https://docs.microsoft.com/en-us/dotnet/api/system.convert.toint32
Long Convert.ToInt64 https://docs.microsoft.com/en-us/dotnet/api/system.convert.toint64
SByte Convert.ToSByte https://docs.microsoft.com/en-us/dotnet/api/system.convert.tosbyte
Short Convert.ToInt16 https://docs.microsoft.com/en-us/dotnet/api/system.convert.toint16
Single Convert.ToSingle https://docs.microsoft.com/en-us/dotnet/api/system.convert.tosingle
String See the ToString Method lesson
UInteger Convert.ToUInt32 https://docs.microsoft.com/en-us/dotnet/api/system.convert.touint32
ULong Convert.ToUInt64 https://docs.microsoft.com/en-us/dotnet/api/system.convert.touint64
UShort Convert.ToUInt16 https://docs.microsoft.com/en-us/dotnet/api/system.convert.touint16

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:

  1. Prompt the user enter enter a Decimal.
  2. Convert the String returned from Console.ReadLine to a Decimal.
  3. 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:

Data-Type Method Documentation
Boolean Boolean.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.boolean.tryparse
Byte Byte.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.byte.tryparse
Char Char.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.char.tryparse
DateTime DateTime.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.datetime.tryparse
Decimal Decimal.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.decimal.tryparse
Double Double.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.double.tryparse
Integer Int32.TryParse or Integer.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse
Long Int64.TryParse or Long.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.int64.tryparse
SByte SByte.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.sbyte.tryparse
Short Int16.TryParse or Short.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.int16.tryparse
Single Single.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.single.tryparse
UInteger UInt32.TryParse or UInteger.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.uint32.tryparse
ULong UInt64.TryParse or ULong.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.uint64.tryparse
UShort UInt16.TryParse or UShort.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.uint16.tryparse

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:

  1. Prompt the user to enter enter a Decimal.
  2. Convert the String returned from Console.ReadLine to a Decimal using TryParse.
  3. Use a Do loop to force the user to enter a valid Decimal.
  4. 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:

  • Cat is the class (the blueprint).
  • minou is an object (an actual instance).
  • Name, Birthday, FurColor, and EyeColor are 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:

  1. Create a Class to represent a desk.
  2. Create the following properties:
    • Number of Drawers
    • Construction Type
    • Color
    • Height
    • Width
    • Length
    • Cost
  3. 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:

  1. Create a Class to represent a desk
  2. Create a property to represent the desk's price
  3. Create an event that gets invoked when the price changes
  4. Create a new instance of the desk
  5. Prompt the user to change the value of the price
  6. Loop until the user enters a valid value
  7. Change the value of the price
  8. 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:

  1. Create a Class to represent a cup.
  2. Create the following properties:
    1. Volume
    2. Material
  3. Create two constructors:
    1. Parameterless constructor that sets the default value of the properties.
    2. 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:

  1. Create a base Class named Vehicle with:
    • A Make property
    • A Model property
    • A method named Describe that prints the make and model
  2. Create a derived Class named Car that:
    • Inherits from Vehicle
    • Has an additional property named Doors
  3. Override the Describe method in Car to include the number of doors.
  4. 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:

  1. Prompt the user to enter 5 numeric values
  2. Validate that the entered values are the correct data-type
  3. 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:

  1. Create a Class named Book with the following properties:
    • Title
    • Author
    • PageCount
  2. Create a collection of several Book objects.
  3. Use a LINQ Select to get only the titles from the collection.
  4. 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:

  1. Create a Class named Book with the following properties:
    • Title
    • Author
    • PageCount
  2. Use a Where clause to filter books that have more than 300 pages.
  3. 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!

Scene in Harry Potter where Griffindor wins the house cup.

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:

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!