Skip to main content
Published / updated

VB.NET Syntax and Project Setup

Before you start

You need: basic programming ideas — variables, conditions, loops. C# from Track 03 helps but is not required; this article explains the differences as they appear.

You need installed: Visual Studio with the .NET desktop development workload.

Time: about 45 minutes, plus the practice.

Learning objective

Open an existing VB.NET project, understand what its compiler options change, and read declarations, types, and operators without guessing.

Topics

  • Why VB.NET applications still run in production
  • .NET Framework versus modern .NET
  • Creating and opening a VB.NET project in Visual Studio
  • Option Strict, Option Explicit, and Option Infer
  • Dim, value and reference types, Nothing
  • Strings, concatenation, and comparison
  • Operators and their C# equivalents

Why this track exists

A large amount of working business software was written in VB.NET between 2002 and roughly 2015: internal admin tools, reporting utilities, Web Forms applications, Office add-ins. That software still processes real transactions, so companies still pay people to maintain it.

You are unlikely to start a new project in VB.NET. You are quite likely, as a fresher, to be handed one and asked why a screen is wrong. The goal here is reading fluency and safe change, not building from scratch.

VB.NET and C# compile to the same intermediate language and use the same base class library. List(Of T) in VB.NET is List<T> in C#. The concepts transfer; the syntax is what stops people.

.NET Framework versus modern .NET

Most legacy VB.NET runs on .NET Framework (4.6.x, 4.7.x, 4.8), which is Windows-only and installed as part of the operating system. Modern .NET supports VB.NET for console and class-library projects, but not for Web Forms or WinForms designers in the same way.

Check .vbproj before assuming anything:

<!-- .NET Framework: old-style project, verbose, lists every file -->
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>

<!-- Modern .NET: SDK-style project, short -->
<TargetFramework>net8.0</TargetFramework>

An old-style .vbproj that lists every source file individually tells you the project predates 2017 tooling. That is useful context before you propose changes.

Opening a VB.NET project in Visual Studio

You will almost always be handed an existing solution rather than starting one.

  1. File → Open → Project/Solution, and pick the .sln.
  2. If a dialog offers to retarget or upgrade the project, say no the first time. Build it as it is, so you learn whether it was working before you touched anything.
  3. Build → Build Solution (Ctrl+Shift+B) and read the Error List before anything else.
  4. Press F5 to run, or Ctrl+F5 for a console project.

If the project will not load at all, Solution Explorer shows it as unavailable and the reason is usually one of three things:

SymptomCauseFix
"The project requires .NET Framework 4.x which is not installed"That targeting pack is missingVisual Studio Installer → Individual components → tick the pack
Project shows as unavailable / load failedMissing workloadAdd .NET desktop development, and ASP.NET and web development for Web Forms
Hundreds of errors about missing typesNuGet packages not restoredRight-click the solution → Restore NuGet Packages, then rebuild

Read the compiler options before reading the code. They are not only at the top of a file — the project-wide defaults live in right-click the project → Properties → Compile:

SettingWhereWhy it matters
Option StrictProperties → CompileOff is the default and hides conversion bugs until run time
Option ExplicitProperties → CompileOn everywhere sane
Option InferProperties → CompileAffects what Dim x = 5 means
Target frameworkProperties → ApplicationTells you which .NET this is

A file-level Option Strict On overrides the project setting for that file only. So one file can be strict inside an otherwise loose project — which is exactly how a team migrates gradually, and why two files can behave differently for no visible reason.

Never "fix" all the warnings the day you arrive. Turning Option Strict On across an old project can produce thousands of errors. Read first; change one thing at a time.

Compiler options — read these first

Three Option settings change what the compiler allows. They appear at the top of a file or in project properties, and they explain most of the surprising code you will meet.

OptionOn meansDefault
Option ExplicitEvery variable must be declaredOn
Option StrictNo implicit narrowing conversions; no late bindingOff
Option InferDim x = 5 infers IntegerOn
Option Explicit On
Option Strict On
Option Infer On

Option Strict Off is the default and is the single biggest source of legacy bugs. With it off, this compiles:

' Option Strict Off — compiles, fails at run time if the text is not a number
Dim marks As Integer
marks = txtMarks.Text

With Option Strict On, that is a compile error and you are forced to write the conversion you meant:

Option Strict On

Dim marks As Integer
If Not Integer.TryParse(txtMarks.Text, marks) Then
ShowError("Marks must be a whole number.")
Return
End If

Turning Option Strict On in an old project usually produces hundreds of errors at once. Do not do it as a casual improvement — it is a planned piece of work, file by file, with testing.

Declarations and types

Dim declares. The type follows the name after As.

Dim studentName As String = "Ravi Kumar"
Dim rollNumber As String = "NCA-2024-0012"
Dim marksObtained As Integer = 87
Dim feeBalance As Decimal = 8000D
Dim isActive As Boolean = True
Dim admittedOn As Date = New Date(2024, 6, 15)

Value types (Integer, Decimal, Boolean, Date, Structure) hold their value directly. Reference types (String, arrays, class instances) hold a reference. Nothing is VB.NET's null, but it also means "the default value" for a value type — assigning Nothing to an Integer gives 0, not an error.

Dim count As Integer = Nothing ' count is 0
Dim name As String = Nothing ' name is a null reference

Use Decimal for money. Double introduces rounding error that shows up in fee totals.

Constants are locals or members fixed at compile time; ReadOnly is a field modifier fixed at construction:

Const MaxMarks As Integer = 100

Private ReadOnly _schoolCode As String = "NCA"

ReadOnly is not valid on a local variable — it appears only on class and structure fields.

Strings

VB.NET uses & for concatenation. + also works on strings, which is exactly why you should not use it — with Option Strict Off, "5" + 3 silently produces 8.

Dim label As String = studentName & " (" & rollNumber & ")"

Comparison is by value with =, unlike C#'s == on references:

If studentName = "Ravi Kumar" Then
' true when the text matches
End If

For case-insensitive comparison, be explicit rather than lowering both sides:

If String.Equals(section, "a", StringComparison.OrdinalIgnoreCase) Then

Other regular arrivals in legacy code:

Dim trimmed As String = studentName.Trim()
Dim upper As String = studentName.ToUpper()
Dim isEmpty As Boolean = String.IsNullOrWhiteSpace(studentName)
Dim parts() As String = rollNumber.Split("-"c)

The "-"c suffix makes a Char rather than a String. Legacy code often uses Split("-"), which works but is a different overload.

Operators

VB.NETC#Note
=== or =Assignment and comparison, decided by context
<>!=Not equal
And / Or& / |Always evaluates both sides
AndAlso / OrElse&& / ||Short-circuits
Not!Negation
&+String concatenation
\/ on integersInteger division
Mod%Remainder
^Math.PowExponent
Is / IsNot== / != on referencesReference identity

The And versus AndAlso distinction matters and is covered in the next article — And evaluates the right side even when the left is already False, which will throw on a null reference.

Comments and line continuation

' Single quote starts a comment

REM This also works and appears in very old code

Dim total As Decimal = feeAccount.TotalFees -
feeAccount.PaidAmount -
feeAccount.DiscountAmount

Modern VB.NET allows implicit line continuation after an operator. Pre-2010 code uses a trailing underscore instead, which you will still see:

Dim total As Decimal = feeAccount.TotalFees _
- feeAccount.PaidAmount

Errors you will hit

MessageCauseFix
BC30451: '<name>' is not declared. It may be inaccessible due to its protection levelTypo, or the file is not in the projectCheck the spelling and Solution Explorer
BC30512: Option Strict On disallows implicit conversions from 'String' to 'Integer'Assigned text to a number with strict onInteger.TryParse it
BC42104: Variable is used before it has been assigned a valueDeclared but never setAssign it at the declaration
BC30203: Identifier expectedUsually a stray line-continuation _ or a broken statementCheck the previous line
The project will not loadMissing targeting pack or workloadSee the table above
Two files behave differently for no reasonOne has a file-level Option Strict OnCheck the top of each file

BC30512 is a good error. It is Option Strict On catching at compile time what would otherwise have been a run-time crash in front of a user.

Common mistakes

  • Assuming Option Strict is On — it is Off by default, and a string assigned to an Integer will compile
  • Turning Option Strict On across an old project in one commit
  • Using Double for fee and payment amounts
  • Using + to join strings, which changes meaning under Option Strict Off
  • Reading = as assignment inside an If, where it is comparison
  • Assuming Nothing behaves like null for value types
  • Editing a .vbproj by hand without noticing it is an old-style project file

Practice

Open any existing VB.NET project. Record its target framework, whether Option Strict is on, and how many files declare their own Option lines. Then find one variable assignment that would fail to compile if Option Strict were turned on, and write the explicit conversion it would need.

You can now

  • Open an existing VB.NET solution and build it
  • Find Option Strict in both the file and the project properties
  • Say why Option Strict Off is the biggest source of legacy bugs
  • Read VB.NET declarations, strings and operators without translating to C# first
  • Tell .NET Framework from modern .NET, and say which you are looking at
  • Diagnose a project that will not load

Review questions

  1. What does Option Strict Off permit that On forbids, and why does it matter in production?
  2. Which type should hold a fee amount, and why not Double?
  3. What is the difference between And and AndAlso?
  4. What does assigning Nothing to an Integer produce?

Next: Conditions and loops