History, Versions and Language Strategy
|
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); .NET 11 was a release candidate that day and is treated as upcoming. It is the page to read when you meet code or documentation that says "VB 10", "Visual Basic 2008" or "VB6", when a project must stay on an older LangVersion, or when you wonder whether Visual Basic is "still alive". The programs on it were built and run with warnings as errors in the official mcr.microsoft.com/dotnet/sdk:10.0 container image, and the compiler messages quoted are real ones. A second purpose of the page is to collect, in one place, the statements of the books behind this reference that have aged badly. For the platform view see Visual Basic and .NET; for the older dialects see The VB Family: VB6, VBA and VBScript.
From BASIC to Visual Basic 6 (1964 to 1998)
BASIC (Beginner’s All-purpose Symbolic Instruction Code) was designed at Dartmouth College in 1964 to let students who were not specialists program a computer. Its descendants spread through the home computers of the 1970s and 1980s and through Microsoft’s own interpreters and compilers. Three of its ideas survive in Visual Basic today: keywords that read as English, a forgiving syntax (no semicolons, case-insensitive names) and the habit of getting a result quickly.
Visual Basic 1.0 appeared in 1991 and combined that language with a visual form designer and an event model: you drew controls on a form and wrote the code that ran when the user clicked them. Versions 2 to 5 added data access, 32-bit support, classes and a native-code compiler, and Visual Basic 6.0 (1998) became the most widely used form of the language. VB6 compiled to native code or to p-code run by a runtime library, used COM for components (ActiveX controls and DLLs) and had its own types (Variant, Integer as a 16-bit type, Type for records). The Visual Basic 6 IDE has been out of support since 2008-04-08; the VB6 runtime is supported "It Just Works" style for the lifetime of the Windows version it ships with, limited to serious regressions and critical security problems, according to Microsoft’s VB6 support statement.
Visual Basic .NET: the break of 2002
Visual Basic .NET (Visual Studio .NET 2002, internally Visual Basic 7) was not an upgrade of VB6. It kept the look of the language and replaced almost everything under it: the runtime (the CLR instead of the VB6 runtime library), the component model (assemblies instead of COM), the type system and the object model. Source code written for VB6 does not compile as it is, and no automatic tool converts a real VB6 application completely. The most visible differences:
| Topic | VB6 | Visual Basic .NET |
|---|---|---|
Integer types |
|
|
Untyped values |
|
|
Records |
|
|
Parameters |
|
|
Inheritance |
Interface implementation only ( |
Single class inheritance with |
Error handling |
|
Structured |
Arrays |
|
Always zero-based; the declared number is the upper bound |
Strings and dates |
|
|
Forms |
|
Classes with a designer partial class; control arrays are gone; events are bound with |
The Option Strict default (off) and the permissive Variant-like conversions that the language still allows by default are the leftovers of that history, and they explain several of the defaults in Option Statements. The detailed VB6-to-VB.NET mapping is on The VB Family: VB6, VBA and VBScript and Migrating Legacy Visual Basic.
The books this section draws on repeat a claim that is wrong in both directions: they present .NET’s "backward compatibility" as an easy road from VB6. Visual Basic .NET has never been source-compatible with VB6. The ease is for the programmer’s habits, not for the code.
Timeline
Source: What’s new for Visual Basic
The version table
Microsoft documents the headline features of each language version on the "What’s new for Visual Basic" page. The table below lists every row of that page, the Visual Studio release it belongs to, and the LangVersion value that selects it. The LangVersion column was checked by building a project with each value on the SDK 10.0.402 compiler; the feature column follows Microsoft’s page.
| Version | Visual Studio | LangVersion |
Headline features |
|---|---|---|---|
7.0 |
Visual Studio .NET 2002 |
not selectable |
The first release of Visual Basic .NET. |
7.1 |
Visual Studio .NET 2003 |
not selectable |
Bit-shift operators, loop variable declaration. |
8.0 |
Visual Studio 2005 |
not selectable |
The |
9.0 |
Visual Studio 2008 |
|
LINQ, XML literals, local type inference, object initializers, anonymous types, extension methods, lambda expressions, the |
10.0 |
Visual Studio 2010 |
|
Automatically implemented properties, collection initializers, implicit line continuation, multi-line lambdas, |
11.0 |
Visual Studio 2012 |
|
|
12.0 |
Visual Studio 2013 |
|
Technology previews of the .NET Compiler Platform ("Roslyn"); no new language feature. |
14.0 |
Visual Studio 2015 |
|
|
15.0 |
Visual Studio 2017 |
|
Tuples, binary literals and digit separators, consumption of C# reference return values. |
15.3 |
Visual Studio 2017 version 15.3 |
|
Named tuple inference; |
15.5 |
Visual Studio 2017 version 15.5 |
|
Non-trailing named arguments, |
16.0 |
Visual Studio 2019 version 16.0 |
|
The first version focused on .NET Core: more of the Visual Basic runtime for .NET Core, comments allowed after explicit line continuations, faster floating-point to integer conversion. |
16.9 |
Visual Studio 2019 version 16.9 |
|
Consumption of init-only properties. |
17.0 |
Visual Studio 2022 |
no value of its own ( |
The compiler honours |
17.13 |
Visual Studio 2026 (first shipped in Visual Studio 2022 version 17.13) |
|
Recognizes the |
Some of these numbers deserve explanation. There is no Visual Basic 13: after 12 (Visual Studio 2013, the Roslyn previews) the numbering jumped to 14, the version of Visual Studio 2015. Version 15 was delivered in three steps (15, 15.3, 15.5), and each step is its own LangVersion value. And version 17 has only one selectable value, 17.13, because 17.0 changed no syntax: it only teaches the compiler to honour an attribute.
One program, many eras
The next program uses one feature from each era, from Visual Basic 9 to 16, newest last. Its output is not important; what matters is that it compiles with the default (latest) language version and that every line is tagged with the version that introduced the feature, so you can recognize them in older code and know what LangVersion is needed.
Option Strict On
' One program, one feature per language version, newest last.
Public Class Shelf
Public Property Name As String ' VB 10: auto-implemented property
Protected Friend Property Capacity As Integer ' (always available)
Private Protected Property Secret As String = "x" ' VB 15.5: Private Protected
End Class
Module Program
Function Describe(title As String, copies As Integer, year As Integer) As String
Return $"{title} ({year}) x{copies}" ' VB 14: interpolated string
End Function
Iterator Function Years() As IEnumerable(Of Integer) ' VB 11: iterators
Yield 1991
Yield 2002
Yield 2008
End Function
Async Function CountLater() As Task(Of Integer) ' VB 11: Async/Await
Await Task.Delay(5)
Return 42
End Function
Sub Main()
Dim shelf As New Shelf With {.Name = "Reference"} ' VB 9: object initializer
Dim parts As New List(Of String) From {"A", "B"} ' VB 10: collection initializer
Dim total As Integer = Years().Sum() +
parts.Count ' VB 10: implicit line continuation
Console.WriteLine(NameOf(shelf) & " " & shelf.Name) ' VB 14: NameOf
Console.WriteLine(Describe(title:="Atlas", copies:=2, year:=1999))
Dim missing As String = Nothing
Console.WriteLine(missing?.Length.ToString() & "[null]") ' VB 14: null-conditional
Dim built As Date = #2002-02-13# ' VB 14: year-first date literal
Console.WriteLine(built.Year)
Dim pair = (Name:="shelf", Count:=3) ' VB 15: tuples
Dim name As String = "late"
Dim count As Integer = 9
Dim inferred = (name, count) ' VB 15.3: inferred tuple names
Console.WriteLine(pair.Name & " " & inferred.name & " " & inferred.count)
Dim mask As Integer = &B0110_1110 ' VB 15: binary literal, separator
Dim big As Integer = &H_C305_F860 ' VB 15.5: leading separator (wraps)
Console.WriteLine(mask & " " & big)
Console.WriteLine(Describe("Atlas", year:=1999, copies:=2)) ' VB 15.5: mixed named arguments
Dim text As String = "a" & _ ' VB 16: a comment is allowed here
"b"
Console.WriteLine(text & " " & total & " " & CountLater().Result)
End Sub
End Module
shelf Reference
Atlas (1999) x2
[null]
2002
shelf late 9
110 -1023018912
Atlas (1999) x2
ab 6003 42
Source: What’s new for Visual Basic
Notice the -1023018912: the literal &H_C305_F860 is a hexadecimal pattern with the top bit set, and a Visual Basic hexadecimal literal assigned to an Integer takes that bit pattern as a negative number. Microsoft’s What’s new text describes the same literal as 3,271,948,384, which is the value of the same 32 bits read as an unsigned number; for an Integer variable the printed value is the negative one.
Selecting the language version: LangVersion
A project compiles with the newest language version the SDK’s compiler supports unless it says otherwise. The LangVersion property of the project file (or -langversion on the compiler command line) restricts the compiler to the syntax of an older version, which is useful when the same code is also built by an older Visual Studio or a build server that has an older SDK.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<OptionStrict>On</OptionStrict>
<LangVersion>15.5</LangVersion>
</PropertyGroup>
</Project>
LangVersion restricts syntax and language rules, nothing else: the APIs available are decided by the target framework, and a net10.0 project with LangVersion 9 can still call every .NET 10 library. The accepted values were found by building the same trivial program with each candidate on SDK 10.0.402:
| Value | Result |
|---|---|
|
Accepted. |
|
Rejected with BC2014: the value is invalid for option |
A newer-than-allowed feature is reported with a language-version error (BC36716 and, for three newer features, specific numbers) that names the version and the feature, so the compiler tells you exactly what to change. These are the real messages produced by a one-feature program built with an older LangVersion; every one of the programs built cleanly with the default version:
| Feature | LangVersion used |
Compiler message |
|---|---|---|
Auto-implemented property |
9 |
BC36716: Visual Basic 9.0 does not support auto-implemented properties. |
Implicit line continuation |
9 |
BC36716: Visual Basic 9.0 does not support implicit line continuation. |
Collection initializer |
9 |
BC36716: Visual Basic 9.0 does not support collection initializers. |
Multi-line lambda |
9 |
BC36716: Visual Basic 9.0 does not support multi-line lambda expressions. |
|
10 |
BC36716: Visual Basic 10.0 does not support async methods or lambdas. |
Iterators |
10 |
BC36716: Visual Basic 10.0 does not support iterators. |
String interpolation |
12 |
BC36716: Visual Basic 12.0 does not support interpolated strings. |
|
12 |
BC36716: Visual Basic 12.0 does not support 'nameof' expressions. |
Null-conditional |
12 |
BC36716: Visual Basic 12.0 does not support null conditional operations. |
Year-first date literal |
12 |
BC36716: Visual Basic 12.0 does not support year-first date literals. |
Multi-line string literal |
12 |
BC36716: Visual Basic 12.0 does not support multiline string literals. |
|
12 |
BC36716: Visual Basic 12.0 does not support TypeOf IsNot expression. |
Tuples |
14 |
BC36716: Visual Basic 14.0 does not support tuples. |
Binary literal |
14 |
BC36716: Visual Basic 14.0 does not support binary literals. |
Digit separator |
14 |
BC36716: Visual Basic 14.0 does not support digit separators. |
Inferred tuple element name |
15 |
BC37289: Tuple element name 'a' is inferred. Please use language version 15.3 or greater to access an element by its inferred name. |
|
15.3 |
BC36716: Visual Basic 15.3 does not support Private Protected. |
Leading separator |
15.3 |
BC36716: Visual Basic 15.3 does not support leading digit separator. |
Non-trailing named argument |
15.3 |
BC30241: Named argument expected. Please use language version 15.5 or greater to use non-trailing named arguments. |
Comment after a line continuation character |
15.5 |
BC37306: Please use language version 16 or greater to use comments after line continuation character. |
Three practical rules follow. First, set LangVersion only when you have a reason; leaving it out keeps you on the latest. Second, setting a lower value never hides APIs, so it is no substitute for choosing the target framework. And third, BC36716 is a message to read for its version number: it tells you the lowest LangVersion the feature needs, which is also a quick way to date an unfamiliar snippet.
The language strategy: consumption-only, shown
Microsoft’s strategy for the language says that Visual Basic will adopt a consumption-only approach to new C# and runtime features: code can use types and members built with them, but the language gets no new syntax to define such types. The two latest versions are exactly that. To show what "consumption" means, a small C# library defines three things that C# and .NET added over the years (the unmanaged constraint from C# 7.3, CallerArgumentExpression from C# 10 and the overload resolution priority attribute from C# 13), and a Visual Basic program consumes them.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Shelf.CSharpLib;
public static class Sizes
{
// C# 'unmanaged' constraint: only types without references qualify.
public static int Of<T>() where T : unmanaged => System.Runtime.CompilerServices.Unsafe.SizeOf<T>();
}
public static class Describer
{
[OverloadResolutionPriority(1)]
public static string Describe(IComparable value) => "preferred overload";
public static string Describe(IEnumerable<char> value) => "enumerable overload";
}
public static class Checks
{
public static string Expect(bool condition, [CallerArgumentExpression(nameof(condition))] string expression = null)
=> condition ? "ok" : "failed: " + expression;
}
Option Strict On
Imports Shelf.CSharpLib
Module Program
Sub Main()
Console.WriteLine("Size of Integer : " & Sizes.Of(Of Integer)())
Console.WriteLine("Size of Double : " & Sizes.Of(Of Double)())
Console.WriteLine("Describe(String): " & Describer.Describe("shelf"))
Dim copies As Integer = 3
Console.WriteLine(Checks.Expect(copies > 5))
End Sub
End Module
Size of Integer : 4
Size of Double : 8
Describe(String): preferred overload
failed: copies > 5
The program is a C# class library next to a Visual Basic console project that references it (Visual Basic cannot write any of the three constructs). Because the compiler knows about them, a String is a valid argument for the overload that the library marked as preferred (without the priority attribute, the call would be ambiguous), the expression text of the argument is filled in for CallerArgumentExpression (the second failed: line shows the text copies > 5 that the Visual Basic compiler passed), and Sizes.Of(Of String)() is refused because String is not an unmanaged type (BC32105 and BC37332). Setting LangVersion to 16.9 in the consuming project turns the first two features off, and the compiler says so:
Program.vb(8,50): error BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint.
Program.vb(9,50): error BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint.
Program.vb(10,60): error BC30521: Overload resolution failed because no accessible 'Describe' is most specific for these arguments:
The BC30521 message is followed by the list of candidate methods, omitted here. In practice a project that consumes a library written for modern C# needs the newest compiler and no LangVersion restriction.
Features that need syntax remain unavailable. Visual Basic has no record, no pattern-matching switch expression, no required members, no primary constructors, no top-level statements, no collection expressions and no declaration of ref returns (it can use ref returns declared in C#, since 15.0). The page Visual Basic for Programmers of Other Languages maps each of them to the Visual Basic idiom, and Interop with C# and Other .NET Languages shows the two-language solution layout.
The strategy over time
-
2020: the stable-language announcement. The Visual Basic team’s post "Visual Basic support planned for .NET 5.0" (2020-03-11) said that Visual Basic would be supported on .NET Core and .NET 5 for class libraries, console applications, Windows Forms, WPF, worker services and ASP.NET Core Web API, and that Microsoft did not plan to evolve the language, to keep it stable and compatible between .NET Framework and .NET Core. Two of the six application types (the worker service and the Web API) never received Visual Basic templates; a reader of the 2020 post should check the template list (
dotnet new list --language VB) before relying on it. -
2021: Visual Basic 17.0. Visual Studio 2022 shipped a compiler that honours
CallerArgumentExpression. It added no syntax. -
2023: the Application Framework on .NET. Microsoft’s post "What’s new for the WinForms Visual Basic Application Framework" (2023-03-09) describes the framework, its project-properties designer, the
Application.myappfile and theApplyApplicationDefaultsevent that was introduced in the .NET 6 time frame. Windows Forms applications in Visual Basic on .NET therefore have the Application Framework, with the sameMystartup model as on .NET Framework. -
2024: the strategy page. The annotated strategy document (last updated 2024-05-29) states the consumption-only policy, the investment in Visual Studio and the focus on core scenarios such as Windows Forms and libraries.
-
2025 and 2026: 17.13. The compiler recognizes the
unmanagedconstraint and the overload-resolution priority attribute, and Microsoft’s What’s new page pairs 17.13 with Visual Studio 2026. The Roslyn "Language Feature Status" page, checked on 2026-10-19, has an empty working-set section for Visual Basic, and the compiler of the .NET 11 release candidate SDK (11.0.100-rc.2) accepts the sameLangVersionvalues as the .NET 10 one, with 17.13 still the highest (17.14 and 18 are rejected with BC2014).
Source: Visual Basic support planned for .NET 5.0, What’s new for the WinForms Visual Basic Application Framework, Roslyn: Language Feature Status
Compiler breaking changes
A language that does not change still has compiler releases, and some of them fix bugs in a way that changes behaviour. Roslyn keeps a document per period with the breaking changes of the Visual Basic compiler (Compiler Breaking Changes - VS2015, post VS2017, VS2019, post VS2019, DotNet 7 and DotNet 10, plus notes on clashing enum members and overflow in the embedded runtime), under docs/compilers/Visual Basic in the Roslyn repository. A change introduced in Visual Studio 2022 version 17.13 and listed in the .NET 10 document concerns iterators: an enumerator that has been disposed must not run any more user code.
Option Strict On
Module Program
Iterator Function Shelves() As IEnumerator(Of String)
Yield "Reference"
Console.WriteLine("this line must not run after disposal")
Yield "Fiction"
End Function
Sub Main()
Dim shelvesEnumerator As IEnumerator(Of String) = Shelves()
Console.WriteLine(shelvesEnumerator.MoveNext())
Console.WriteLine(shelvesEnumerator.Current)
shelvesEnumerator.Dispose()
Console.WriteLine(shelvesEnumerator.MoveNext())
End Sub
End Module
True
Reference
False
Before 17.13 the last MoveNext could resume the method after the Yield; now it returns False without executing the Console.WriteLine. Such changes are rare and documented; reading the document for your SDK before a major upgrade is cheap insurance. The general upgrade steps are on Libraries, Packaging and Deployment and Projects, MSBuild and the dotnet CLI.
The specification and where later features are documented
The Visual Basic Language Specification on Microsoft Learn describes the language of Visual Basic 11, the version of Visual Studio 2012; the Learn index page introduces it as the reference for the language grammar and rules. Everything added afterwards (version 14 and later) is documented in two other places: Microsoft’s What’s new pages and Language Reference pages, and the Roslyn repository, whose LanguageVersion.vb source is the authoritative list of language versions. The dotnet/vblang repository is the home of language proposals and specification drafts for Visual Basic; it receives few changes now, which matches the strategy. A reader looking for the exact grammar of a feature added after Visual Basic 11 (tuples, for example) usually finds the answer in the What’s new page, the Language Reference page of the keyword, and the Roslyn tests, not in the specification.
Gaps and errors in the official documentation
| Where | What was found on 2026-10-19 |
|---|---|
The Learn pages "Select the Visual Basic language version" and "-langversion" |
Their tables of valid values stop at 16.9 and do not list 17.13, although the compiler accepts it (and |
The Learn Like Operator page |
It carries a note that |
The Learn "What’s new" page |
It describes the hexadecimal example with a leading separator as 3,271,948,384; assigned to an |
The Learn error-message pages |
Some very common messages (BC30451, BC30002, BC42104) have no page of their own under the Learn |
Where the books are outdated
This section collects every statement of the two books used for the section that is out of date, with the current position. Each topic is also covered, with the examples, on the page named in the last column. The books' own errors (as opposed to their age) are not repeated here: wherever a page covers the concept, it states the correct rule in prose.
| Area | What the books say | Current state (checked on 2026-10-19) | Page |
|---|---|---|---|
Runtime |
Visual Basic "is part of the .NET Framework"; the console template is "Console App (.NET Framework)". |
Visual Basic targets .NET 10 through the SDK (console, libraries, Windows Forms, WPF). .NET Framework 4.8.1 is maintenance-only. |
|
Visual Studio |
Use Visual Studio 2022, or 2019 because 2022 supposedly lacks Visual Basic ASP.NET. |
Visual Studio 2026 is current. It still offers "ASP.NET Web Application (.NET Framework)" for Visual Basic; only ASP.NET Core has no Visual Basic support. |
|
Language evolution |
".NET 6 and beyond" brings new Visual Basic features. |
No new syntax since 16.9; versions 17.0 and 17.13 only consume features. .NET 6 has been out of support since November 2024. |
This page |
Web |
ASP.NET Core, SignalR with the |
No Visual Basic templates and no Razor syntax; the |
|
Mobile |
A chapter on Xamarin. |
Xamarin support ended on 2024-05-01; .NET MAUI does not support Visual Basic. |
|
Desktop |
Windows Forms is cross-platform; WPF "runs on the web" (XBAP). |
Both are Windows-only; XBAP is gone; use |
|
Windows services |
An installer component plus |
A hosted |
|
Data access |
|
|
|
Serialization |
|
Removed in .NET 9; use System.Text.Json, |
|
HTTP |
|
Obsolete (SYSLIB0014): use |
|
Cryptography |
|
Obsolete (SYSLIB0021): use |
|
COM |
COM interop "does not work with .NET Core or .NET 5+"; |
.NET on Windows supports COM clients ( |
|
Packages |
|
|
|
Diagnostics |
Glimpse, Visual Studio Load Test, performance counters. |
|
|
Deployment |
UWP and the Store; "make sure the .NET Framework is installed". |
MSIX for Windows Forms and WPF; framework-dependent with the Desktop Runtime, or self-contained and single-file publishing. |
|
Legacy dialects |
"VBScript is supported by all modern versions of Windows"; Mono as a Visual Basic compiler; installing VB6 from an archive site. |
VBScript is deprecated and is being removed in phases; Mono’s |
|
Migration |
Visual Basic .NET’s "backward compatibility" eases the move from VB6. |
Visual Basic .NET was never source-compatible with VB6; no tool converts a real VB6 application completely. |
Common mistakes on this page’s topics
| Mistake | Fix |
|---|---|
Writing |
BC2014. Use |
Assuming a lower |
It restricts syntax only. The target framework decides the APIs. |
Treating "Visual Basic 2010" and "VB 10" as different things. |
They are the same: Visual Basic 10.0 shipped with Visual Studio 2010. Names with a year and names with a number refer to the same release. |
Looking for a Visual Basic 13. |
There is none; the numbering went from 12 to 14. |
Copying Visual Basic 6 code and hoping a few edits are enough. |
The type sizes, the default parameter passing, the object model and the library all differ. See the legacy pages. |
Expecting the newest C# syntax to be available because the compiler is the same Roslyn platform. |
Visual Basic and C# share the compiler infrastructure but not their languages. Visual Basic consumes the results of C# features; it does not get their syntax. |
Reading the 2020 announcement as the current list of VB workloads. |
Check |
References
-
Visual Basic support planned for .NET 5.0 (2020-03-11)
-
What’s new for the WinForms Visual Basic Application Framework (2023-03-09)
-
Select the Visual Basic language version and -langversion compiler option
-
Roslyn: LanguageVersion.vb and Roslyn: Language Feature Status
-
Roslyn: Visual Basic compiler breaking changes, .NET 9 to .NET 10