Visual Basic and .NET
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page was checked on 2026-10-19 against Visual Basic 17.13 on .NET 10 (LTS, SDK 10.0.402). The examples were built and run with warnings as errors in the official mcr.microsoft.com/dotnet/sdk:10.0 image; a few Windows-only builds are labelled. It answers two questions before the language chapters start. First: what is Visual Basic on .NET, in the vocabulary of the platform (runtime, assemblies, types), so that the rest of the reference can talk about Integer and System.Int32 interchangeably. Second, and more practical for anyone starting a project: which kinds of application can be built in Visual Basic on .NET 10 today, and which cannot. The first project of the section is on Getting Started. The platform itself (CLR internals, garbage collection, the JIT, the base class library) is shared with C# and is described in C# and .NET; this page covers what is specific to Visual Basic.
Visual Basic is a .NET language
A .NET language is a compiler that turns source code into Common Intermediate Language (IL) plus metadata, packaged as an assembly. Everything below the compiler is shared by C#, F# and Visual Basic.
| Platform term | What it means for Visual Basic code |
|---|---|
Common Language Runtime (CLR) |
The execution engine. It loads assemblies, compiles IL to native code with the JIT compiler ( |
Intermediate Language (IL) |
The instruction set that |
Metadata |
Tables inside the assembly that describe every type, member, attribute and reference. Because it is language-neutral, a VB class can be used from C# (and the reverse) without a wrapper. |
Assembly |
The deployable unit: a |
Base class library (BCL) |
|
The Common Type System and Visual Basic’s names
Visual Basic does not define its own Integer: the keyword is an alias for a type of the Common Type System (CTS), exactly like int in C#. Learning the pairs once removes a whole category of confusion, because every .NET API documents the CLR name, while VB code usually writes the keyword. The next program prints each alias and the type behind it.
Option Strict On
Module Program
Sub Show(keyword As String, clrType As Type)
Console.WriteLine($"{keyword,-8} = {clrType.FullName,-18} {If(clrType.IsValueType, "value type", "reference type")}")
End Sub
Sub Main()
Show("Boolean", GetType(Boolean))
Show("Byte", GetType(Byte))
Show("SByte", GetType(SByte))
Show("Short", GetType(Short))
Show("UShort", GetType(UShort))
Show("Integer", GetType(Integer))
Show("UInteger", GetType(UInteger))
Show("Long", GetType(Long))
Show("ULong", GetType(ULong))
Show("Single", GetType(Single))
Show("Double", GetType(Double))
Show("Decimal", GetType(Decimal))
Show("Char", GetType(Char))
Show("String", GetType(String))
Show("Date", GetType(Date))
Show("Object", GetType(Object))
Dim n As Integer = 7
Dim viaClr As Int32 = n
Console.WriteLine(n.GetType() Is viaClr.GetType())
Console.WriteLine(n.CompareTo(8) & " " & Integer.MaxValue & " " & Int32.MinValue)
End Sub
End Module
Boolean = System.Boolean value type
Byte = System.Byte value type
SByte = System.SByte value type
Short = System.Int16 value type
UShort = System.UInt16 value type
Integer = System.Int32 value type
UInteger = System.UInt32 value type
Long = System.Int64 value type
ULong = System.UInt64 value type
Single = System.Single value type
Double = System.Double value type
Decimal = System.Decimal value type
Char = System.Char value type
String = System.String reference type
Date = System.DateTime value type
Object = System.Object reference type
True
-1 2147483647 -2147483648
Three observations from the output. Short is the 16-bit integer and Integer the 32-bit one; C# calls them short and int, and Visual Basic 6 called them Integer and Long, which is why old code needs a careful translation (see The VB Family: VB6, VBA and VBScript). Date is a Visual Basic name for System.DateTime (VB has no separate DateTime keyword, though the type name also works). And the unsigned types UShort, UInteger and ULong exist in the language but are not CLS-compliant, so a public API meant for every .NET language avoids them. The full table, with ranges and literals, is on Data Types and Literals. Everything is an Object in the end, as in C#: value types derive from System.ValueType, which derives from System.Object.
.NET and .NET Framework
Two .NET products exist for Visual Basic code, and most of the confusion in older material comes from mixing them.
| .NET (the unified platform; .NET 5 and later, current: .NET 10) | .NET Framework 4.8.1 | |
|---|---|---|
Platforms |
Windows, Linux and macOS (the Windows-only UI frameworks run on Windows) |
Windows only, part of the operating system |
Status |
Actively developed; .NET 10 is an LTS release supported until 2028-11-14. .NET 11 was a release candidate on 2026-10-19 and is upcoming (it was not generally available when this was checked). |
The last version of .NET Framework. It follows the lifecycle of the Windows version it ships with and receives only maintenance. |
Visual Basic |
Compiled by the SDK’s Roslyn compiler, current language 17.13. All new work belongs here. |
Same compiler and language, but the project files can be the old style, and the full Visual Basic runtime ( |
Web |
ASP.NET Core (no Visual Basic templates or Razor syntax). |
ASP.NET Web Forms and ASP.NET MVC 5, where Visual Basic is fully supported. |
Tooling |
The |
Visual Studio 2026 still opens and builds these projects. MSBuild and the |
Target framework monikers
BinaryFormatter being the best known, covered on Serialization, JSON and XML). The porting step that matters most for Visual Basic is to replace the old-style .vbproj (with explicit file lists, My Project folders and references by assembly) with an SDK-style project; the legacy page Migrating Legacy Visual Basic walks through it.Every project declares what it runs on with TargetFramework, a short name (a target framework moniker, TFM). The compiler references the matching set of assemblies and the SDK adds the matching runtime configuration.
| TFM | Meaning for a Visual Basic project |
|---|---|
|
.NET 10 on any supported operating system. The default for a console application, a class library, a test project, a worker. |
|
.NET 10 plus the Windows-only API surface: Windows Forms ( |
|
Windows with a specific Windows SDK version, for code that calls the newer Windows runtime APIs. |
|
.NET Framework 4.8.1. The reference assemblies come from a NuGet package, so even this builds on Linux (checked with the container). Used for existing Web Forms, MVC 5 and Office add-in projects, and for libraries that must still be used by .NET Framework code. |
|
The .NET Standard contract, for a library shared between .NET and .NET Framework. For new libraries a multi-target such as |
The next program reads its own target framework and the assemblies it references, which shows the moniker is a real attribute stored in the assembly.
Option Strict On
Imports System.Reflection
Imports System.Runtime.Versioning
Module Program
Sub Main()
Dim entry As Assembly = Assembly.GetEntryAssembly()
Dim target As TargetFrameworkAttribute = entry.GetCustomAttribute(Of TargetFrameworkAttribute)()
Console.WriteLine("Target framework : " & target.FrameworkName)
Console.WriteLine("Display name : " & target.FrameworkDisplayName)
Console.WriteLine("Runtime version : " & Environment.Version.ToString())
Console.WriteLine("Is 64-bit process: " & Environment.Is64BitProcess)
Console.WriteLine("Module : " & entry.ManifestModule.Name)
For Each reference As AssemblyName In entry.GetReferencedAssemblies()
Console.WriteLine("References : " & reference.Name & " " & reference.Version.ToString())
Next
End Sub
End Module
Target framework : .NETCoreApp,Version=v10.0
Display name : .NET 10.0
Runtime version : 10.0.13
Is 64-bit process: True
Module : tfm.dll
References : System.Runtime 10.0.0.0
References : Microsoft.VisualBasic.Core 15.0.0.0
References : System.Console 10.0.0.0
The last block of lines shows the Visual Basic runtime as an ordinary reference of the program (Microsoft.VisualBasic.Core, assembly version 15.0.0.0, a number that has nothing to do with the language version), next to System.Runtime and System.Console. The container’s runtime was 10.0.13 and the module name is the project name of the scratch project.
What can be built with Visual Basic on .NET 10
This is the question the issue behind this reference calls "can I build X in VB on .NET 10?". The answer depends on the application model, and it is not the same as for C#. Microsoft’s language strategy says that Visual Basic is not extended to new workloads, and that is visible in the templates: dotnet new offers VB for console, class library, MSTest, NUnit, xUnit, Windows Forms, WPF and its library variants, and nothing else.
The diagram is a decision aid, not a rule of the compiler: Visual Basic compiles any project the SDK hands to it, and the rest of this section is about what is supported, which is what determines templates, documentation, designers and help when something goes wrong.
App-model support matrix
| Application model | dotnet new template for VB |
Supported for VB | How, and the catch |
|---|---|---|---|
Console application |
|
Yes |
|
Class library |
|
Yes |
Packaged as a NuGet package or consumed by a project reference, also from C# applications. Page: Libraries, Packaging and Deployment. |
Unit tests (MSTest, xUnit, NUnit) |
|
Yes |
All three frameworks work with VB. Page: Testing. |
Windows Forms |
|
Yes, Windows only |
|
WPF |
|
Yes, Windows only |
|
Worker service, Windows service |
none |
Yes, hand-written |
The 2020 announcement listed "Worker Service" too, but no VB template exists today. Reference |
ASP.NET Web Forms, ASP.NET MVC 5 |
none on .NET |
Yes, .NET Framework only |
Visual Studio 2026 keeps the "ASP.NET Web Application (.NET Framework)" project for VB. They run on IIS with .NET Framework 4.8.1 and have no .NET 10 version. See the existing sections ASP.NET Web Forms and ASP.NET MVC. |
ASP.NET Core (minimal APIs, controllers) |
none |
No (no template, no VB documentation) |
The practical pattern is a C# web host that references a Visual Basic class library. A hand-written VB host builds (checked below), but there is no template, no Razor syntax and no documentation in VB. Microsoft’s March 2020 announcement of Visual Basic on .NET 5 listed "ASP.NET Core Web API" among the planned application types, yet the SDK used here ships no VB template for it, and the language strategy now says new workloads are not planned. See ASP.NET Core. |
Razor Pages, MVC views, Blazor |
none |
No |
Razor has no Visual Basic syntax, so there is nothing to author these in VB. |
gRPC services |
none |
No template |
Same position as ASP.NET Core: possible only as library code behind a C# host. |
.NET MAUI |
none |
No |
MAUI does not support Visual Basic. Use C# for the app and a VB class library for shared logic. |
Xamarin |
none |
No |
Xamarin support ended on 2024-05-01 (see the Xamarin support policy), and it was never a Visual Basic scenario. |
WinUI 3 |
none |
No |
C# or C++ only; a VB library can be referenced. |
Office automation, COM, VSTO add-ins |
none |
Yes, with caveats |
COM interop works on .NET on Windows; VSTO add-ins are .NET Framework. Page: COM Interop and Office Automation. |
A worker service written by hand
There is no worker template for Visual Basic, but the hosting library is ordinary .NET and works from VB. The project file selects the Worker SDK and references the hosting package; the code is a BackgroundService registered with AddHostedService.
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<RootNamespace>Shelf.Worker</RootNamespace>
<TargetFramework>net10.0</TargetFramework>
<OptionStrict>On</OptionStrict>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
</ItemGroup>
</Project>
Option Strict On
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Hosting
Imports Microsoft.Extensions.Logging
''' <summary>Counts overdue loans once, then asks the host to stop.</summary>
Public Class OverdueSweeper
Inherits BackgroundService
Private ReadOnly _logger As ILogger(Of OverdueSweeper)
Private ReadOnly _lifetime As IHostApplicationLifetime
Public Sub New(logger As ILogger(Of OverdueSweeper), lifetime As IHostApplicationLifetime)
_logger = logger
_lifetime = lifetime
End Sub
Protected Overrides Async Function ExecuteAsync(stoppingToken As Threading.CancellationToken) As Task
Await Task.Delay(10, stoppingToken)
_logger.LogWarning("Sweep finished: {Overdue} overdue loans", 3)
_lifetime.StopApplication()
End Function
End Class
Module Program
Sub Main(args As String())
Dim builder = Host.CreateApplicationBuilder(args)
builder.Logging.SetMinimumLevel(LogLevel.Warning)
builder.Services.AddHostedService(Of OverdueSweeper)()
Dim app = builder.Build()
app.Run()
End Sub
End Module
warn: Shelf.Worker.OverdueSweeper[0]
Sweep finished: 3 overdue loans
Two Visual Basic points are visible in the listing and in the attempts that led to it. A local variable named host is refused when the same method also uses the type Host, because names are case-insensitive: the compiler reports BC32000 ("Local variable 'host' cannot be referred to before it is declared"), so the example calls the local app. And Async Function ... As Task is how an asynchronous method is written, with Await inside; the language has no Async Main, so the entry point stays a synchronous Sub Main and the host does the waiting (see Async and Await). Adding builder.Services.AddWindowsService(Sub(options) options.ServiceName = "Shelf") with the Microsoft.Extensions.Hosting.WindowsServices package turns the same program into a Windows service; that variant built without warnings, but running it as a service needs Windows and sc.exe.
An ASP.NET Core host in Visual Basic: unsupported territory
The last rows of the matrix can be tested. A project with the Microsoft.NET.Sdk.Web SDK and the Program.vb below compiled and ran on .NET 10. It is shown only to make the boundary concrete; it is not a recommendation.
Option Strict On
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Http
Imports Microsoft.Extensions.Hosting
Module Program
Sub Main(args As String())
Dim builder = WebApplication.CreateBuilder(args)
Dim app = builder.Build()
app.MapGet("/ping", Function() "pong")
Console.WriteLine("built " & app.GetType().Name)
End Sub
End Module
built WebApplication
The program builds the application and exits without starting the listener (it never calls app.Run()), so it only shows that the web libraries can be called from VB. It does not make ASP.NET Core a supported Visual Basic workload (the 2020 announcement of Visual Basic on .NET 5 mentioned a Web API, but the templates never followed): there is no template, the Razor and Blazor view engines have no VB syntax, the ASP.NET Core documentation shows C#, and the language strategy states that new workloads are not planned. Treat a Visual Basic web host as an experiment and a Visual Basic library behind a C# host as the supported design. Web Forms and MVC 5 stay on .NET Framework; see Web, HTTP and Services.
The Visual Basic runtime library
Part of what makes Visual Basic code look the way it does is a library, not the compiler: Left, Mid, Len, Format, CInt, Val, IsNumeric, Rnd, DateAdd, FileOpen, the Collection class, the Like operator helpers, the late-binding helpers, MsgBox and InputBox, and the My namespace. On .NET it is split across a few assemblies.
| Assembly | Contents |
|---|---|
|
The runtime proper: the |
|
A small assembly in the shared framework next to the core one, for code that references the old assembly name. |
|
The Windows Forms part, available with the Windows desktop runtime: |
|
The VB6 compatibility classes (control arrays, |
Some of these facts are visible at run time. On a plain net10.0 project Left, Mid, Format and CInt work, and the types Interaction, Strings, LikeOperator and TextFieldParser all live in Microsoft.VisualBasic.Core (checked by asking each type for its assembly name). MsgBox and InputBox compile on plain net10.0, but the dialogs need Windows Forms: calling MsgBox("Hello") from the Linux container threw System.PlatformNotSupportedException with the message "Method requires System.Windows.Forms." That is why the dialogs belong to Windows desktop programs and not to console tools, as The My Namespace explains.
Embedding the runtime: the VBRuntime property
The SDK decides how the compiler gets the Visual Basic runtime, and its own Visual Basic targets file documents the rule in a comment. On .NET Core 3.0 and later it finds Microsoft.VisualBasic among the references and passes it to the compiler as the runtime (-vbruntime), so the program references Microsoft.VisualBasic.Core at run time. For .NET Core before 3.0 and for .NET Standard, where no complete runtime assembly exists, it embeds the runtime’s code into your assembly (VBRuntime set to Embed). On .NET Framework the compiler uses the Microsoft.VisualBasic.dll of the framework folder. Two properties override the default: UseReferencedVBRuntime set to true forces a referenced runtime, and a non-empty VBRuntime is passed through to the compiler unchanged.
Setting VBRuntime to Embed in a net10.0 project and running the earlier reflection program gives the following output, with no Microsoft.VisualBasic.Core among the references:
Target framework : .NETCoreApp,Version=v10.0
Display name : .NET 10.0
Runtime version : 10.0.13
Is 64-bit process: True
Module : emb.dll
References : System.Runtime 10.0.0.0
References : System.Console 10.0.0.0
Source: -vbruntime compiler option
Embedding makes the assembly self-sufficient for the Visual Basic helpers (useful for a library that targets many frameworks) at the price of copying the needed code into every assembly that embeds it. For ordinary applications the default, a reference, is right. A related caution applies to the late-binding helpers: they use reflection and are annotated as not safe for trimming, so a program that relies on late binding (see Early and Late Binding) cannot be trimmed or compiled ahead of time reliably.
MyType: the My namespace is optional on .NET
My is not part of the runtime library; the compiler generates it into your project from a property called MyType. On .NET Framework projects the default is a full My. On .NET, the SDK sets MyType to Empty for every target that is not .NET Framework (its comment says the Visual Basic runtime did not support My.* outside .NET Framework when this was written) and leaves it to the project templates to select a non-empty value when it makes sense. The consequences, checked on the SDK used here:
-
A console project and a class library have no
My.Computer,My.Application,My.User,My.SettingsorMy.Resources. Using one gives an error such asBC30456: 'Computer' is not a member of 't1.My', wheret1is the project’s own root namespace. -
Setting
MyTypetoConsoleon a plainnet10.0project does not help: the generated code needs types fromMicrosoft.VisualBasic.Forms, and the compiler reports BC30002 forMicrosoft.VisualBasic.Devices.ComputerandConsoleApplicationBase. -
On
net10.0-windowswithUseWindowsFormsset totrue, settingMyTypetoWindows,WindowsForms,WindowsFormsWithCustomSubMainorConsolegave a project in whichMy.Computer.ClockandMy.Application.Infocompiled (built, not run). -
The
winformstemplate of the SDK used here writes aSub Mainand does not setMyType, soMy.*is also empty in a freshly generatednet10.0-windowsWindows Forms project until you set the property.
This is why My-based examples from older books and blog posts fail to compile in a new project. The details of every My object, and of what is available where, are on The My Namespace, and the Application Framework is on Windows Forms Applications.
The language strategy, in practice
The official strategy document, last updated on 2024-05-29, says in short: Visual Basic stays an approachable language with a stable design; the core .NET libraries support it, and most runtime and library improvements benefit it automatically; where C# or the runtime add features that need language support, Visual Basic takes a consumption-only approach and avoids new syntax; it will not be extended to new workloads; and Microsoft keeps investing in the Visual Studio experience and in interoperation with C#, especially for Windows Forms and libraries.
What this means for a reader and for a project:
-
Consumption-only means you can call new .NET APIs and use types that depend on new runtime features, but you cannot declare such types or use the new syntax. Visual Basic 17.13, the latest version, recognizes the
unmanagedconstraint and the overload-resolution-priority attribute when they appear in a library written in C#; it does not let you write them. The version history is on History, Versions and Language Strategy. -
The language you learn now is the language that will be there later: code written today is not made obsolete by syntax changes. The price is that features other languages have (records, pattern matching,
requiredmembers, primary constructors, top-level statements, collection expressions) do not exist in Visual Basic, and Visual Basic for Programmers of Other Languages lists the idioms to use instead. -
New workloads are not planned, which is the reason for the "no" rows of the matrix. Teams that need them usually write the front in C# and keep the Visual Basic code as a library, which works because of the shared assembly format (see Interop with C# and Other .NET Languages).
-
The compiler and the runtime library ship with every .NET release, so a VB project follows the .NET support calendar. The risk to plan for is the surrounding ecosystem (samples, templates, third-party libraries that document C# only), not the language.
Where the books are outdated for this page
| What the books say | Current state (checked on 2026-10-19) |
|---|---|
Visual Basic "is part of the .NET Framework" and its console templates are .NET Framework ones. |
It is a .NET language and targets .NET 10 through the SDK for console, library, Windows Forms and WPF projects. .NET Framework 4.8.1 remains for maintenance. |
ASP.NET Core, SignalR with the old |
There are no Visual Basic templates for ASP.NET Core or Blazor, and Razor has no VB syntax. The |
Windows Forms can be cross-platform, and WPF applications run in the browser. |
Windows Forms and WPF are Windows-only. The browser-hosted WPF form (XBAP) is gone; WPF is selected with |
A whole chapter on mobile apps with Xamarin. |
Xamarin support ended on 2024-05-01 and .NET MAUI does not support Visual Basic. |
".NET 6 and beyond" brings new Visual Basic features, and Visual Basic has a future as a growing language. |
The language has had no new syntax since 16.9; later versions only consume features from C# and the runtime. .NET 6 itself has been out of support since November 2024. |
|
On .NET 5 and later some of these come from NuGet packages or have a successor ( |
Common mistakes on this page’s topics
| Mistake | Fix |
|---|---|
Starting a new project on .NET Framework because a tutorial did. |
Use |
Expecting |
|
Calling |
They need Windows Forms and throw |
Treating the keyword |
They are the same type. Choose one style per project; VB code conventionally uses the keywords, and |
Naming a local variable like a type used in the same method ( |
Names are case-insensitive, so the local hides the type and the compiler reports BC32000. Pick another name. |
Looking for a |
None exists. Write the worker by hand, or host the VB library from a C# project. |
Targeting |
Multi-target |
References
-
Common Language Runtime (CLR) overview and Common Type System
-
.NET and .NET Core support policy, .NET Framework documentation and Xamarin support policy
-
Microsoft.VisualBasic namespace and Visual Basic: developing applications
-
Worker Services in .NET and Create a Windows Service using BackgroundService