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 (dotnet run does not produce machine code ahead of time), manages memory with the garbage collector and enforces type safety. A VB program starts in the same runtime process as a C# one.

Intermediate Language (IL)

The instruction set that vbc emits. A Sub or Function becomes an IL method. The constructs that exist only in VB (With, Handles, Select Case, XML literals, My) are translated by the compiler into ordinary IL, sometimes with helper calls into the Visual Basic runtime library.

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. Public, Friend and Private are written in VB, but the metadata says public, assembly and private.

Assembly

The deployable unit: a .dll (or an executable .dll with an apphost). One project produces one assembly. See Namespaces, Assemblies and Projects for the platform view and Libraries, Packaging and Deployment for the VB view.

Base class library (BCL)

System, System.IO, System.Linq, System.Text.Json and the rest. VB uses them directly; the Visual Basic runtime library adds a layer of VB-flavoured helpers on top (Left, Mid, Format, CInt, MsgBox).

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 (My with all its services, My.WebServices, Microsoft.VisualBasic.Compatibility.VB6) lives here.

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 dotnet command, Visual Studio 2026.

Visual Studio 2026 still opens and builds these projects. MSBuild and the .NET Framework targeting packs are used.

Target framework monikers

NET 8 and .NET 9 both reach the end of support on 2026-11-10, so a Visual Basic project targeting them should move to .NET 10. Code written for the old runtime is not automatically broken by that move: the Visual Basic language itself is unchanged, and the differences are in the framework (APIs that were removed, 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

net10.0

.NET 10 on any supported operating system. The default for a console application, a class library, a test project, a worker.

net10.0-windows

.NET 10 plus the Windows-only API surface: Windows Forms (UseWindowsForms), WPF (UseWPF), the registry, COM interop, the My.Computer devices and the Visual Basic MsgBox and InputBox functions. A project with this moniker builds on Linux and macOS only with EnableWindowsTargeting set to true, and it can only run on Windows.

net10.0-windows10.0.19041.0 (and similar)

Windows with a specific Windows SDK version, for code that calls the newer Windows runtime APIs.

net481

.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.

netstandard2.0, netstandard2.1

The .NET Standard contract, for a library shared between .NET and .NET Framework. For new libraries a multi-target such as net10.0;net481 is the current practice; .NET Standard is only needed for old consumers. The SDK embeds the Visual Basic runtime into assemblies that target .NET Standard (see below).

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.

flowchart TD Q["I want to build X in Visual Basic on .NET 10"] --> A{"What kind of application?"} A --> C["Console tool, class library, unit tests"] C --> Y1["Yes: dotnet new console, classlib, mstest, xunit or nunit with -lang VB"] A --> D["Windows desktop UI: Windows Forms or WPF"] D --> Y2["Yes, on Windows only: net10.0-windows, templates winforms and wpf"] A --> E["Background worker or Windows service"] E --> Y3["Yes, hand-written: no VB worker template, add Microsoft.Extensions.Hosting yourself"] A --> F["Web application or web API"] F --> G{"Which web stack?"} G --> H["ASP.NET Web Forms or MVC 5"] H --> N1[".NET Framework 4.8.1 only: net481 and IIS"] G --> I["ASP.NET Core minimal API or controllers"] I --> N2["Through a C# host that references your VB class library; a VB host compiles but is unsupported"] G --> J["Razor Pages, MVC views, Blazor, gRPC"] J --> N3["No: no VB templates and Razor has no VB syntax"] A --> K["Mobile or cross-platform UI: MAUI, Xamarin, WinUI 3"] K --> N4["No: use a C# project that consumes your VB library"]

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

console

Yes

Module with Sub Main. No Async Main, no top-level statements. Page: Console Applications.

Class library

classlib

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)

mstest, xunit, nunit

Yes

All three frameworks work with VB. Page: Testing.

Windows Forms

winforms, winformslib, winformscontrollib

Yes, Windows only

net10.0-windows with UseWindowsForms. Cross-platform Windows Forms does not exist. Page: Windows Forms Applications.

WPF

wpf, wpflib, wpfcustomcontrollib, wpfusercontrollib

Yes, Windows only

net10.0-windows with UseWPF. XAML plus VB code-behind. The browser-hosted XBAP form is gone. Page: WPF Applications.

Worker service, Windows service

none

Yes, hand-written

The 2020 announcement listed "Worker Service" too, but no VB template exists today. Reference Microsoft.Extensions.Hosting, write a BackgroundService; add Microsoft.Extensions.Hosting.WindowsServices and AddWindowsService for a Windows service. Checked below.

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

Microsoft.VisualBasic.Core

The runtime proper: the Strings, Conversion, Information, Interaction, DateAndTime, FileSystem, Financial and Constants modules; Collection; the Microsoft.VisualBasic.CompilerServices helpers that the compiler calls for operators such as Like, for late binding and for conversions; and Microsoft.VisualBasic.FileIO (TextFieldParser). It ships with the .NET runtime and every VB project references it automatically.

Microsoft.VisualBasic (the facade)

A small assembly in the shared framework next to the core one, for code that references the old assembly name.

Microsoft.VisualBasic.Forms

The Windows Forms part, available with the Windows desktop runtime: Microsoft.VisualBasic.ApplicationServices (the Application Framework), Microsoft.VisualBasic.Devices (Computer, Clock, Keyboard, Mouse and so on), the My services and the dialogs behind MsgBox and InputBox.

Microsoft.VisualBasic.Compatibility.VB6

The VB6 compatibility classes (control arrays, Font helpers). It exists only for .NET Framework.

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

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.Settings or My.Resources. Using one gives an error such as BC30456: 'Computer' is not a member of 't1.My', where t1 is the project’s own root namespace.

  • Setting MyType to Console on a plain net10.0 project does not help: the generated code needs types from Microsoft.VisualBasic.Forms, and the compiler reports BC30002 for Microsoft.VisualBasic.Devices.Computer and ConsoleApplicationBase.

  • On net10.0-windows with UseWindowsForms set to true, setting MyType to Windows, WindowsForms, WindowsFormsWithCustomSubMain or Console gave a project in which My.Computer.Clock and My.Application.Info compiled (built, not run).

  • The winforms template of the SDK used here writes a Sub Main and does not set MyType, so My.* is also empty in a freshly generated net10.0-windows Windows 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 unmanaged constraint 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, required members, 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 Startup pattern, and Blazor are presented as things to write in VB.NET.

There are no Visual Basic templates for ASP.NET Core or Blazor, and Razor has no VB syntax. The Startup class pattern has been replaced by minimal hosting. Web Forms and MVC 5 are the supported VB web stacks, on .NET Framework and IIS only.

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 UseWPF in a net10.0-windows project.

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.

System.IO.Ports, System.Runtime.Caching and similar are part of the base framework.

On .NET 5 and later some of these come from NuGet packages or have a successor (Microsoft.Extensions.Caching.Memory).

Common mistakes on this page’s topics

Mistake Fix

Starting a new project on .NET Framework because a tutorial did.

Use net10.0 (or net10.0-windows). Keep net481 for existing Web Forms and MVC 5 code and for libraries that .NET Framework consumers still need.

Expecting My.Computer in a console project.

My is empty on .NET unless MyType is set and the Windows desktop pieces are present. Use System.IO.File, Environment, RuntimeInformation and the other BCL APIs instead.

Calling MsgBox or InputBox from a console or service program.

They need Windows Forms and throw PlatformNotSupportedException elsewhere. Use Console.WriteLine and Console.ReadLine.

Treating the keyword Integer and the CLR name Int32 as different types.

They are the same type. Choose one style per project; VB code conventionally uses the keywords, and Int32 appears in calls such as Int32.TryParse.

Naming a local variable like a type used in the same method (host and Host).

Names are case-insensitive, so the local hides the type and the compiler reports BC32000. Pick another name.

Looking for a worker, webapi or blazor template with -lang VB.

None exists. Write the worker by hand, or host the VB library from a C# project.

Targeting netstandard2.0 for a new library "to be safe".

Multi-target net10.0;net481 when .NET Framework consumers exist, and just net10.0 otherwise.