The Visual Basic Runtime Library
|
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 is written against Visual Basic 17.13 on .NET 10 (SDK 10.0.402) and was checked on 2026-10-19. Every example is a complete console program that
starts with Option Strict On, was built with warnings treated as errors (unless the text says otherwise) and was run in the .NET 10 SDK container (Linux, arm64); the output shown is
real output. Several programs have a Sub Main selected with the StartupObject property in one project whose root namespace is ShelfRt. The SDK imports System, System.Collections.Generic,
System.IO, System.Linq and others project-wide, and the compiler always imports Microsoft.VisualBasic, which is why Left, Len, Now, Choose and vbCrLf need no Imports line.
The Visual Basic runtime library is the assembly of helper functions, constants and types that ships with the language. It is the part of Visual Basic that old programs call most (Mid, InStr, Format, CInt, MsgBox,
FileOpen, Err) and that new code should call with care: some of it is a thin layer over the BCL, some is a Visual Basic 6 compatibility layer whose behaviour differs from the BCL in one-based indexes, culture
and null handling, some is Windows-only, and a little is obsolete. This page maps the library, measures what the .NET assembly really contains, and gives each area a tested example. Topics that have their own page are summarised and linked:
strings on Strings and Text, conversions on Type Conversions,
dates on Dates, Times and Formatting, numbers and the financial functions on
Numbers and Math, and My on The My Namespace.
What the library is on .NET
On .NET Framework the whole library was Microsoft.VisualBasic.dll. On .NET it is split in two assemblies of the shared framework: Microsoft.VisualBasic.Core, which holds the runtime that every Visual Basic program references, and a small
Microsoft.VisualBasic assembly next to it for code that refers to the old assembly name. The Windows Forms parts (My.Computer, the Application Framework, the dialogs behind MsgBox and InputBox) are in a third assembly,
Microsoft.VisualBasic.Forms, that ships with the Windows Desktop runtime (see The My Namespace).
The program below asks Microsoft.VisualBasic.Core what it exports, grouping the public types of each namespace by kind. A Visual Basic Module compiles to a sealed class marked with StandardModuleAttribute, so the program uses that attribute to recognise modules:
Option Strict On
Imports System.Reflection
Imports Microsoft.VisualBasic.CompilerServices
Module Program
Private Function Kind(t As Type) As String
If t.IsEnum Then Return "Enum"
If t.IsInterface Then Return "Interface"
If t.IsSubclassOf(GetType(MulticastDelegate)) Then Return "Delegate"
If t.IsSubclassOf(GetType(Attribute)) Then Return "Attribute"
If t.IsDefined(GetType(StandardModuleAttribute), False) Then Return "Module"
If t.IsValueType Then Return "Structure"
Return "Class"
End Function
Sub Main()
Dim asm As Assembly = GetType(Microsoft.VisualBasic.Strings).Assembly
For Each ns As String In {"Microsoft.VisualBasic", "Microsoft.VisualBasic.CompilerServices", "Microsoft.VisualBasic.FileIO"}
Console.WriteLine("== " & ns)
Dim groups As New SortedDictionary(Of String, List(Of String))()
For Each t As Type In asm.GetExportedTypes()
If t.Namespace = ns Then
Dim k As String = Kind(t)
If Not groups.ContainsKey(k) Then groups(k) = New List(Of String)()
groups(k).Add(t.Name)
End If
Next
For Each kv In groups
kv.Value.Sort()
Console.WriteLine(kv.Key & ": " & String.Join(", ", kv.Value))
Next
Next
End Sub
End Module
== Microsoft.VisualBasic
Attribute: ComClassAttribute, HideModuleNameAttribute, MyGroupCollectionAttribute, VBFixedArrayAttribute, VBFixedStringAttribute
Class: Collection, ControlChars, ErrObject
Enum: AppWinStyle, CallType, CompareMethod, DateFormat, DateInterval, DueDate, FileAttribute, FirstDayOfWeek, FirstWeekOfYear, MsgBoxResult, MsgBoxStyle, OpenAccess, OpenMode, OpenShare, TriState, VariantType, VbStrConv
Module: Constants, Conversion, DateAndTime, FileSystem, Financial, Information, Interaction, Strings, VBMath
Structure: SpcInfo, TabInfo
== Microsoft.VisualBasic.CompilerServices
Attribute: DesignerGeneratedAttribute, OptionCompareAttribute, OptionTextAttribute, StandardModuleAttribute
Class: BooleanType, ByteType, CharArrayType, CharType, Conversions, DateType, DecimalType, DoubleType, ForLoopControl, IncompleteInitialization, IntegerType, LateBinding, LikeOperator, LongType, NewLateBinding, ObjectFlowControl, ObjectType, Operators, ProjectData, ShortType, SingleType, StaticLocalInitFlag, StringType, Utils, Versioned
== Microsoft.VisualBasic.FileIO
Class: FileSystem, MalformedLineException, SpecialDirectories, TextFieldParser
Enum: DeleteDirectoryOption, FieldType, RecycleOption, SearchOption, UICancelOption, UIOption
Source: Microsoft.VisualBasic namespace
So the library is small: nine modules, three classes (Collection, ControlChars, ErrObject), seventeen enumerations, five attributes and two structures in Microsoft.VisualBasic; a set of compiler helper classes in CompilerServices;
and TextFieldParser, FileSystem, SpecialDirectories and their option enumerations in FileIO. Everything that follows is an instance of this list.
| Module or type | Contents | Usually better today |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
keep (no BCL equivalent), but use |
|
|
|
|
|
|
|
the one-based, keyed VB6 collection |
|
|
the |
exceptions |
|
|
same, or |
(The member lists are the documented ones for the classic modules; the next program measures the counts.)
What is hidden, obsolete or Windows-only
The assembly records its own warnings as attributes, and the compiler and analyzers act on them, so reflection can list them. The program below goes through every public static member of the nine modules and counts those hidden from IntelliSense,
marked obsolete, annotated as supported only on Windows (SupportedOSPlatform) or unsupported on some platforms, or marked as unsafe for trimming (RequiresUnreferencedCode). It then prints each obsolete member with its message, and each platform annotation.
(In Visual Basic a variable declared in a loop body keeps its value between iterations, so the counters are re-initialised at the top of the loop body.)
Option Strict On
Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.Versioning
Imports Microsoft.VisualBasic.CompilerServices
Module Program
Sub Main()
Dim asm As Assembly = GetType(Microsoft.VisualBasic.Strings).Assembly
Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Static Or BindingFlags.DeclaredOnly
Console.WriteLine("module members hidden obsolete unsupported-os supported-os needs-unreferenced-code")
For Each t As Type In asm.GetExportedTypes().OrderBy(Function(x) x.Name)
If t.Namespace = "Microsoft.VisualBasic" AndAlso t.IsDefined(GetType(StandardModuleAttribute), False) Then
Dim total As Integer = 0, hidden As Integer = 0, obs As Integer = 0
Dim unsup As Integer = 0, sup As Integer = 0, ruc As Integer = 0
For Each m As MemberInfo In t.GetMembers(flags)
If TypeOf m Is MethodInfo AndAlso DirectCast(m, MethodInfo).IsSpecialName Then Continue For
total += 1
Dim eb = m.GetCustomAttribute(Of EditorBrowsableAttribute)()
If eb IsNot Nothing AndAlso eb.State = EditorBrowsableState.Never Then hidden += 1
If m.IsDefined(GetType(ObsoleteAttribute), False) Then obs += 1
If m.IsDefined(GetType(UnsupportedOSPlatformAttribute), False) Then unsup += 1
If m.IsDefined(GetType(SupportedOSPlatformAttribute), False) Then sup += 1
If m.IsDefined(GetType(System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute), False) Then ruc += 1
Next
Console.WriteLine(t.Name.PadRight(18) & total.ToString().PadLeft(5) & hidden.ToString().PadLeft(8) & obs.ToString().PadLeft(9) & unsup.ToString().PadLeft(13) & sup.ToString().PadLeft(14) & ruc.ToString().PadLeft(14))
End If
Next
Console.WriteLine("--- obsolete members")
For Each t As Type In asm.GetExportedTypes().OrderBy(Function(x) x.Name)
For Each m As MemberInfo In t.GetMembers(BindingFlags.Public Or BindingFlags.Static Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
Dim o = m.GetCustomAttribute(Of ObsoleteAttribute)()
If o IsNot Nothing Then
Dim msg As String = If(o.Message, "")
Console.WriteLine(t.Name & "." & m.Name & " : " & msg)
End If
Next
Dim ot = t.GetCustomAttribute(Of ObsoleteAttribute)()
If ot IsNot Nothing Then Console.WriteLine("TYPE " & t.Name & " : " & ot.Message)
Next
Console.WriteLine("--- platform attributes")
For Each t As Type In asm.GetExportedTypes().OrderBy(Function(x) x.Name)
For Each m As MemberInfo In t.GetMembers(BindingFlags.Public Or BindingFlags.Static Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
For Each a In m.GetCustomAttributes(False)
If TypeOf a Is OSPlatformAttribute Then
Console.WriteLine(t.Name & "." & m.Name & " : " & a.GetType().Name & " " & DirectCast(a, OSPlatformAttribute).PlatformName)
End If
Next
Next
Next
End Sub
End Module
Condensed output (the full platform list repeats an entry for every overload):
module members hidden obsolete unsupported-os supported-os needs-unreferenced-code
Constants 102 0 1 0 0 0
Conversion 40 0 0 0 0 2
DateAndTime 25 0 0 0 0 0
FileSystem 83 0 1 7 5 7
Financial 13 0 0 0 0 0
Information 17 0 0 0 0 0
Interaction 20 0 0 0 7 3
Strings 57 0 0 0 1 1
VBMath 4 0 0 0 0 0
--- obsolete members
Constants.vbNewLine : vbNewLine has been deprecated. For a carriage return and line feed, use vbCrLf. For the current platform's newline, use System.Environment.NewLine.
Conversions.FallbackUserDefinedConversion : FallbackUserDefinedConversion has been deprecated and is not supported.
FileSystem.FilePut : FileSystem.FilePut has been deprecated. Use FilePutObject to write Object types, or coerce FileNumber and RecordNumber to Integer for writing non-Object types.
MalformedLineException.GetObjectData : This API supports obsolete formatter-based serialization. It should not be called or extended by application code.
NewLateBinding.FallbackCall : FallbackCall has been deprecated and is not supported.
NewLateBinding.FallbackInvokeDefault1 : FallbackInvokeDefault1 has been deprecated and is not supported.
NewLateBinding.FallbackInvokeDefault2 : FallbackInvokeDefault2 has been deprecated and is not supported.
NewLateBinding.FallbackGet : FallbackGet has been deprecated and is not supported.
NewLateBinding.FallbackIndexSetComplex : FallbackIndexSetComplex has been deprecated and is not supported.
NewLateBinding.FallbackIndexSet : FallbackIndexSet has been deprecated and is not supported.
NewLateBinding.FallbackSetComplex : FallbackSetComplex has been deprecated and is not supported.
NewLateBinding.FallbackSet : FallbackSet has been deprecated and is not supported.
Operators.FallbackInvokeUserDefinedOperator : FallbackInvokeUserDefinedOperator has been deprecated and is not supported.
--- platform attributes (member: annotation)
DateAndTime.set_Today: SupportedOSPlatform windows
DateAndTime.set_TimeOfDay: SupportedOSPlatform windows
DateAndTime.set_TimeString: SupportedOSPlatform windows
DateAndTime.set_DateString: SupportedOSPlatform windows
FileSystem.ChDrive: SupportedOSPlatform windows
FileSystem.CurDir: SupportedOSPlatform windows
FileSystem.Dir: SupportedOSPlatform windows
FileSystem.InputString: UnsupportedOSPlatform ios, UnsupportedOSPlatform macos, UnsupportedOSPlatform tvos
FileSystem.Lock: UnsupportedOSPlatform ios, UnsupportedOSPlatform macos, UnsupportedOSPlatform tvos
FileSystem.Unlock: UnsupportedOSPlatform ios, UnsupportedOSPlatform macos, UnsupportedOSPlatform tvos
FileSystem.Rename: SupportedOSPlatform windows
Interaction.Beep: SupportedOSPlatform windows
Interaction.DeleteSetting: SupportedOSPlatform windows
Interaction.GetAllSettings: SupportedOSPlatform windows
Interaction.GetSetting: SupportedOSPlatform windows
Interaction.SaveSetting: SupportedOSPlatform windows
Interaction.CreateObject: SupportedOSPlatform windows
Interaction.GetObject: SupportedOSPlatform windows
Strings.StrConv: SupportedOSPlatform windows
What this means in practice:
-
Obsolete. Only two public members of the nine modules are obsolete: the constant
vbNewLineand theFilePutoverload that takes anObject. TheFallback...members ofNewLateBindingandOperatorsare compiler plumbing that must not be called. Both obsolete members are shown in "Constants" below. -
Windows-only.
Beep, the registry settings functions (GetSetting,SaveSetting,DeleteSetting,GetAllSettings),CreateObject/GetObject(COM),StrConv,Dir,Rename,CurDir,ChDriveand the setters ofToday,TimeOfDay,DateStringandTimeStringcarrySupportedOSPlatform("windows"). A call from code that can run elsewhere makes the analyzer rule CA1416 report them, and withTreatWarningsAsErrorsthe build fails (see the example in "Constants" below).Lock,UnlockandInputStringare unsupported on iOS, macOS and tvOS. An annotation is a warning that the call may not work, not proof that it does not:Dirworked in the file example below on Linux, whileRenamethrew andShell,MsgBoxandInputBoxhave no annotation but threw too. -
Not trim-safe.
Conversion.CTypeDynamic(two overloads),Interaction.CallByName,CreateObject,GetObject,FileGet,FilePut,FileGetObject,FilePutObject,Inputand theLenoverload forObjectare markedRequiresUnreferencedCode, because they use reflection; avoid them in programs that are trimmed or compiled ahead of time (see Early and Late Binding). -
Hidden. None of the module members is hidden from IntelliSense, but all 29 types of
Microsoft.VisualBasic.CompilerServicesare (see below).
Strings
The Strings module is the VB6 string library: functions with one-based positions, tolerant of Nothing, with an optional Compare argument that follows Option Compare. The BCL equivalents are zero-based and throw on Nothing.
Both can be right; the point is to know which one a piece of code uses. The details of every function are on Strings and Text; this program shows the differences that cause bugs:
Option Strict On
Imports System.Globalization
Module StringsTour
Private Sub Try1(label As String, action As Func(Of String))
Try
Console.WriteLine(label & " = " & action())
Catch ex As Exception
Console.WriteLine(label & " -> " & ex.GetType().Name & ": " & ex.Message)
End Try
End Sub
Sub Main()
Dim title As String = "The Left Hand of Darkness"
Dim missing As String = Nothing
Console.WriteLine("-- one-based positions")
Console.WriteLine("InStr(title, ""Left"") = " & InStr(title, "Left").ToString())
Console.WriteLine("title.IndexOf(""Left"") = " & title.IndexOf("Left").ToString())
Console.WriteLine("Mid(title, 5, 4) = " & Mid(title, 5, 4))
Console.WriteLine("title.Substring(4, 4) = " & title.Substring(4, 4))
Console.WriteLine("Left / Right = " & Left(title, 3) & " / " & Right(title, 8))
Console.WriteLine("InStr(6, title, ""e"") = " & InStr(6, title, "e").ToString())
Console.WriteLine("InStrRev(title, ""e"") = " & InStrRev(title, "e").ToString())
Console.WriteLine("-- Nothing is tolerated")
Console.WriteLine("Len(Nothing) = " & Len(missing).ToString())
Console.WriteLine("UCase(Nothing) is empty = " & (UCase(missing).Length = 0).ToString())
Console.WriteLine("Left(Nothing, 3) is empty = " & (Left(missing, 3).Length = 0).ToString())
Try1("missing.Length", Function() missing.Length.ToString())
Console.WriteLine("-- but bad arguments still throw")
Try1("Mid(title, 0)", Function() Mid(title, 0))
Try1("Left(title, -1)", Function() Left(title, -1))
Try1("title.Substring(40)", Function() title.Substring(40))
Console.WriteLine("Left(title, 100) = " & Left(title, 100))
Console.WriteLine("Mid(title, 100) = '" & Mid(title, 100) & "'")
Console.WriteLine("-- whitespace and padding")
Console.WriteLine("[" & Trim(" a b ") & "] [" & LTrim(" a") & "] [" & RTrim("a ") & "]")
Console.WriteLine("Trim leaves tabs: " & (Trim(vbTab & "a" & vbTab).Length).ToString() & " vs String.Trim: " & (vbTab & "a" & vbTab).Trim().Length.ToString())
Console.WriteLine("[" & Space(3) & "] [" & StrDup(3, "ab") & "] [" & StrReverse("Dune") & "]")
Console.WriteLine("[" & LSet("ab", 5) & "] [" & RSet("ab", 5) & "]")
Console.WriteLine("-- characters and codes")
Console.WriteLine("Asc(""A"") = " & Asc("A").ToString() & ", Chr(66) = " & Chr(66) & ", AscW(""é"") = " & AscW("é").ToString() & ", ChrW(&H263A) = " & ChrW(&H263A))
Console.WriteLine("-- Replace, Split, Join, Filter")
Console.WriteLine(Replace(title, "the", "A", 1, 1, CompareMethod.Text))
Console.WriteLine(Replace("a-b-c-d", "-", "+", 3))
Dim parts As String() = Split("Dune;Emma;;Ulysses", ";")
Console.WriteLine(parts.Length.ToString() & " parts, Join = " & Join(parts, "|"))
Console.WriteLine("Filter: " & Join(Filter(parts, "e", True, CompareMethod.Text), ","))
Console.WriteLine("-- formatting helpers (en-US)")
CultureInfo.CurrentCulture = New CultureInfo("en-US")
Console.WriteLine(FormatNumber(1234567.891, 2) & " | " & FormatCurrency(19.5) & " | " & FormatPercent(0.256, 1) & " | " & Format(1234.5, "#,##0.00"))
Console.WriteLine(FormatNumber(-3.5, 1, TriState.UseDefault, TriState.True) & " | " & FormatNumber(0.5, 2, TriState.False))
End Sub
End Module
-- one-based positions
InStr(title, "Left") = 5
title.IndexOf("Left") = 4
Mid(title, 5, 4) = Left
title.Substring(4, 4) = Left
Left / Right = The / Darkness
InStr(6, title, "e") = 6
InStrRev(title, "e") = 23
-- Nothing is tolerated
Len(Nothing) = 0
UCase(Nothing) is empty = True
Left(Nothing, 3) is empty = True
missing.Length -> NullReferenceException: Object reference not set to an instance of an object.
-- but bad arguments still throw
Mid(title, 0) -> ArgumentException: Argument 'Start' must be greater than zero. (Parameter 'Start')
Left(title, -1) -> ArgumentException: Argument 'Length' must be greater or equal to zero. (Parameter 'Length')
title.Substring(40) -> ArgumentOutOfRangeException: startIndex cannot be larger than length of string. (Parameter 'startIndex')
Left(title, 100) = The Left Hand of Darkness
Mid(title, 100) = ''
-- whitespace and padding
[a b] [a] [a]
Trim leaves tabs: 3 vs String.Trim: 1
[ ] [aaa] [enuD]
[ab ] [ ab]
-- characters and codes
Asc("A") = 65, Chr(66) = B, AscW("é") = 233, ChrW(&H263A) = ☺
-- Replace, Split, Join, Filter
A Left Hand of Darkness
b+c+d
4 parts, Join = Dune|Emma||Ulysses
Filter: Dune,Emma,Ulysses
-- formatting helpers (en-US)
1,234,567.89 | $19.50 | 25.6% | 1,234.50
(3.5) | .50
Source: Strings module
Points the output makes concrete:
-
InStrreturns 5 whereIndexOfreturns 4, andInStrreturns 0 for "not found" whereIndexOfreturns -1.Mid(title, 5, 4)andSubstring(4, 4)are the same slice. -
Len,UCase,Leftand the other functions treatNothingas the empty string; the member callmissing.LengththrowsNullReferenceException. -
The functions still validate their arguments: a start of 0 or a negative length throws
ArgumentExceptionwith the VB-style message "Argument 'Start' must be greater than zero.". But a length that is too long is clipped (Left(title, 100)), and a start beyond the end gives an empty string, whereSubstringthrows. -
Trim,LTrimandRTrimremove spaces only: the string with tabs aroundakeeps length 3, whereString.Trim()gives 1. -
Replace(expression, find, replacement, start, count, compare)with astartgreater than 1 returns only the text fromstart:Replace("a-b-c-d", "-", "+", 3)printedb+c+d, and the first characters are gone. This is the most surprising function in the module. -
Format,FormatNumber,FormatCurrencyandFormatPercentuse the current culture, which is why the program setsen-USfirst (in the invariant culture the currency symbol is a generic sign). TheTriStatearguments choose the leading zero, the parentheses for negative numbers and the grouping. -
StrConvwithVbStrConv.ProperCaseand the Japanese and Chinese conversions is annotated as Windows-only;TextInfo.ToTitleCaseis the cross-platform way. -
The module has
Space,StrDup,StrReverseandLSet/RSet(fixed-width padding), which have no one-word BCL equivalent.StrReversereverses UTF-16 code units, so it breaks surrogate pairs and combining marks.
Conversion
The Conversion module has the number-to-text and number-to-integer helpers of VB6. They interact with the conversion keywords (CInt, CStr, CDate, which are compiler features, not functions of this module) described on
Type Conversions.
Option Strict On
Module ConversionTour
Sub Main()
Console.WriteLine("-- Val reads the leading number only, always with the invariant format")
Console.WriteLine(Val("1234abc").ToString() & " " & Val(" 3.5e2xyz").ToString() & " " & Val("&H1F").ToString() & " " & Val("&O17").ToString() & " " & Val("abc").ToString() & " " & Val("1,5").ToString())
Console.WriteLine("-- Str keeps a sign column")
Console.WriteLine("[" & Str(42) & "] [" & Str(-42) & "] [" & CStr(42) & "]")
Console.WriteLine("-- Hex and Oct")
Console.WriteLine(Hex(255) & " " & Hex(-1) & " " & Oct(8) & " " & Hex(CByte(10)))
Console.WriteLine("-- Fix and Int")
Console.WriteLine(Fix(-2.7).ToString() & " " & Int(-2.7).ToString() & " " & Fix(2.7).ToString() & " " & Int(2.7).ToString())
Console.WriteLine("-- CInt rounds to even; CType from Object")
Console.WriteLine(CInt(2.5).ToString() & " " & CInt(3.5).ToString() & " " & CInt(CObj("12")).ToString())
Console.WriteLine("-- CTypeDynamic converts at run time")
Console.WriteLine(CTypeDynamic(Of Integer)("77").ToString() & " " & CTypeDynamic(Of Date)("2026-10-19").ToString("yyyy-MM-dd"))
Console.WriteLine("-- ErrorToString")
Console.WriteLine(ErrorToString(5))
Console.WriteLine(ErrorToString(11))
Console.WriteLine(ErrorToString(0).Length.ToString())
End Sub
End Module
-- Val reads the leading number only, always with the invariant format
1234 350 31 15 0 1
-- Str keeps a sign column
[ 42] [-42] [42]
-- Hex and Oct
FF FFFFFFFF 10 A
-- Fix and Int
-2 -3 2 2
-- CInt rounds to even; CType from Object
2 4 12
-- CTypeDynamic converts at run time
77 2026-10-19
-- ErrorToString
Procedure call or argument is not valid.
Division by zero.
0
Source: Conversion module
-
Valreads the leading characters that look like a number, never throws, always uses the period as the decimal separator, and understands&Hand&Oprefixes.Val("1,5")is 1, not 1.5, andVal("abc")is 0 with no way to tell "not a number" from zero. UseDouble.TryParsewith a culture when you must distinguish the cases. -
Strreserves a column for the sign, so positive numbers get a leading space;CStrdoes not. Code that comparesStr(42)with "42" fails. -
Hex(-1)isFFFFFFFFbecause-1is anInteger; the result depends on the argument’s type.Fixtruncates toward zero andIntrounds down.CInt(2.5)is 2 andCInt(3.5)is 4: banker’s rounding. -
ErrorToString(n)gives the VB6 message for an error number; 0 gives an empty string. -
CTypeDynamicconverts at run time by the type’sIConvertibleor conversion operators and is marked as not trim-safe.
DateAndTime
The module holds the VB date functions and the properties Now, Today, TimeOfDay, Timer, DateString and TimeString. Most of them are shorter spellings of DateTime members; DateAdd, DateDiff and DatePart take an interval, either the DateInterval enumeration or the VB6 string codes ("d", "m", "yyyy").
Option Strict On
Imports System.Globalization
Module DateTour
Sub Main()
CultureInfo.CurrentCulture = New CultureInfo("en-US")
Dim d As Date = #10/19/2026 2:30:00 PM#
Console.WriteLine("-- DateAdd, DateDiff, DatePart")
Console.WriteLine(DateAdd(DateInterval.Month, 3, d).ToString("yyyy-MM-dd"))
Console.WriteLine(DateAdd("d", -19, d).ToString("yyyy-MM-dd"))
Console.WriteLine(DateDiff(DateInterval.Day, #12/31/2025#, #1/1/2026#).ToString() & " day, " & DateDiff(DateInterval.Year, #12/31/2025#, #1/1/2026#).ToString() & " year, " & DateDiff(DateInterval.Month, #12/31/2025#, #1/1/2026#).ToString() & " month")
Console.WriteLine("Weekday difference: " & DateDiff(DateInterval.Weekday, #10/19/2026#, #10/26/2026#).ToString())
Console.WriteLine("Quarter " & DatePart(DateInterval.Quarter, d).ToString() & ", day of year " & DatePart(DateInterval.DayOfYear, d).ToString() & ", week " & DatePart(DateInterval.WeekOfYear, d).ToString())
Console.WriteLine("-- Day names depend on the culture and on the first day of the week")
Console.WriteLine(Weekday(d).ToString() & " " & Weekday(d, FirstDayOfWeek.Monday).ToString() & " " & WeekdayName(Weekday(d), False) & " " & WeekdayName(Weekday(d), True) & " " & MonthName(Month(d)))
Console.WriteLine("-- DateSerial and TimeSerial overflow into the next unit")
Console.WriteLine(DateSerial(2026, 14, 35).ToString("yyyy-MM-dd") & " " & TimeSerial(25, 70, 0).ToString("HH:mm") & " " & DateSerial(2026, 3, 0).ToString("yyyy-MM-dd"))
Console.WriteLine("-- DateValue, TimeValue, Format, Timer")
Console.WriteLine(DateValue("October 19, 2026").ToString("yyyy-MM-dd") & " " & TimeValue("2:30 PM").ToString("HH:mm") & " " & Format(d, "dddd d MMMM yyyy") & " " & Format(d, "Long Date"))
Console.WriteLine((Timer >= 0 AndAlso Timer < 86400).ToString() & " " & Hour(d).ToString() & ":" & Minute(d).ToString() & ":" & Second(d).ToString() & " " & (Now > d).ToString() & " " & (Today = Now.Date).ToString())
Console.WriteLine("-- IsDate")
Console.WriteLine(IsDate("2026-10-19").ToString() & " " & IsDate("19/10/2026").ToString() & " " & IsDate("10/19/2026").ToString() & " " & IsDate("not a date").ToString())
End Sub
End Module
-- DateAdd, DateDiff, DatePart
2027-01-19
2026-09-30
1 day, 1 year, 1 month
Weekday difference: 1
Quarter 4, day of year 292, week 43
-- Day names depend on the culture and on the first day of the week
2 1 Monday Mon October
-- DateSerial and TimeSerial overflow into the next unit
2027-03-07 02:10 2026-02-28
-- DateValue, TimeValue, Format, Timer
2026-10-19 14:30 Monday 19 October 2026 Monday, October 19, 2026
True 14:30:0 True True
-- IsDate
True False True False
Source: DateAndTime module
-
DateDiffcounts boundaries crossed, not elapsed time: from 31 December to 1 January it reports 1 day, 1 year and 1 month. For elapsed time subtract the dates and use theTimeSpan. -
DateDiff(DateInterval.Weekday, ...)counts how many times the weekday of the first date occurs, so Monday to the next Monday is 1. -
DateSerial(2026, 14, 35)does not throw: months and days overflow into the next unit (14 is February of 2027, and the 35th rolls into March).DateSerial(2026, 3, 0)is the last day of February. This helps for "last day of the month" and hides typos. -
Weekdayis one-based with Sunday as 1 unless theFirstDayOfWeekargument says otherwise (Mondaygives 1 for a Monday);WeekdayNameandMonthNameuse the current culture. -
IsDate("19/10/2026")isFalseunderen-US: the result depends on the culture. UseDateTime.TryParseExactfor a fixed format. -
The setters of
Today,TimeOfDay,DateStringandTimeStringchange the system clock and are Windows-only; the program above only reads them.Timeris the number of seconds since midnight, which wraps; useStopwatchfor measuring.
Interaction
Interaction is the grab bag: dialogs, process start, environment, late binding and a few selection functions.
Option Strict On
Imports System.Globalization
Public Class Book
Public Property Title As String = "Dune"
Public Property Pages As Integer = 412
Public Function Describe(prefix As String) As String
Return prefix & Title & " (" & Pages.ToString() & " pages)"
End Function
End Class
Module InteractionTour
Private Function Boom() As String
Console.WriteLine(" (Boom was evaluated)")
Return "boom"
End Function
Sub Main(args As String())
Console.WriteLine("-- Choose: one-based, every argument is evaluated")
Dim kind As Integer = 2
Console.WriteLine(Choose(kind, "Hardcover", "Paperback", Boom()))
Console.WriteLine("out of range gives Nothing: " & (Choose(5, "a", "b") Is Nothing).ToString())
Console.WriteLine("-- Switch: first True expression wins, all are evaluated")
Dim pages As Integer = 412
Dim size As Object = Interaction.Switch(pages < 100, "short", pages < 300, "medium", pages >= 300, "long")
Console.WriteLine(size)
Console.WriteLine("no match gives Nothing: " & (Interaction.Switch(pages < 0, "negative") Is Nothing).ToString())
Console.WriteLine("-- Command and Environ")
Console.WriteLine("Command() = '" & Command() & "' (" & args.Length.ToString() & " arguments)")
Environment.SetEnvironmentVariable("SHELF_MODE", "demo")
Console.WriteLine("Environ(""SHELF_MODE"") = " & Environ("SHELF_MODE"))
Console.WriteLine("Environ(""SHELF_MISSING"") = '" & Environ("SHELF_MISSING") & "'")
Console.WriteLine("Environ(1) contains '=' : " & Environ(1).Contains("=").ToString())
Console.WriteLine("-- CallByName: late-bound access by name")
Dim b As New Book()
CallByName(b, "Pages", CallType.Let, 500)
Console.WriteLine(CStr(CallByName(b, "Title", CallType.Get)) & " " & CStr(CallByName(b, "Pages", CallType.Get)))
Console.WriteLine(CStr(CallByName(b, "Describe", CallType.Method, "Book: ")))
Try
CallByName(b, "Missing", CallType.Get)
Catch ex As MissingMemberException
Console.WriteLine(ex.GetType().Name & ": " & ex.Message)
End Try
Console.WriteLine("-- Partition")
Console.WriteLine(Partition(412, 0, 1000, 250) & " | " & Partition(5, 0, 100, 10) & " | " & Partition(-3, 0, 100, 10) & " | " & Partition(250, 0, 1000, 250))
Console.WriteLine("-- Shell")
Try
Dim id As Integer = Shell("/bin/echo started", AppWinStyle.Hide, False)
Console.WriteLine("Shell returned a process id: " & (id > 0).ToString())
Catch ex As Exception
Console.WriteLine(ex.GetType().Name & ": " & ex.Message)
End Try
End Sub
End Module
-- Choose: one-based, every argument is evaluated
(Boom was evaluated)
Paperback
out of range gives Nothing: True
-- Switch: first True expression wins, all are evaluated
long
no match gives Nothing: True
-- Command and Environ
Command() = 'a "b c"' (2 arguments)
Environ("SHELF_MODE") = demo
Environ("SHELF_MISSING") = ''
Environ(1) contains '=' : True
-- CallByName: late-bound access by name
Dune 500
Book: Dune (500 pages)
MissingMemberException: Public member 'Missing' on type 'Book' not found.
-- Partition
250: 499 | 0: 9 | : -1 | 250: 499
-- Shell
PlatformNotSupportedException: Method requires System.Windows.Forms.
Source: Interaction module
-
The module name conflicts with a type of
System.Diagnostics: the plain nameSwitchis theSwitchclass (the SDK importsSystem.Diagnostics), andSwitch(...)is rejected with BC30109 ("'Switch' is a class type and cannot be used as an expression"). WriteInteraction.Switch. -
ChooseandInteraction.Switchevaluate every argument, as the message printed byBoom()shows, and returnNothing(not an exception) when the index is out of range or no condition is true. TheIfoperator andSelect Caseevaluate only what they need.Chooseis one-based. -
Command()returns the arguments joined into one string (a "b c"), already in a form that has lost the original splitting; take theargsparameter ofMaininstead. -
Environ("NAME")returns an empty string for a missing variable;Environ(1)is the first variable by index and is"NAME=value".Environment.GetEnvironmentVariablereturnsNothingwhen missing. -
CallByNameis late binding by name withCallType.Get,Let,SetandMethod. A missing member throwsMissingMemberException. It is slower than a direct call and unsafe for trimming; see Early and Late Binding. -
Partitionbuilds the label of the bucket that contains a number (" 250: 499"), padded to the width of the largest number. -
ShellthrewPlatformNotSupportedExceptionon Linux; useProcess.Start(see Best Practices and Common Pitfalls).MsgBoxandInputBoxneed Windows Forms (the dialogs example is on The My Namespace). -
GetSetting,SaveSetting,DeleteSetting,GetAllSettings,CreateObject,GetObjectandBeepare Windows-only.CreateObject("Excel.Application")is the COM route described on COM Interop and Office Automation.
Information
Option Strict On
Imports System.Globalization
Module InformationTour
Sub Main()
CultureInfo.CurrentCulture = New CultureInfo("en-US")
Console.WriteLine("-- IsNumeric accepts more than Double.TryParse")
For Each s As String In {"42", " 42 ", "-1.5", "1e3", "$12", "(5)", "&HFF", "&O17", "1,000", "12abc", ""}
Dim parsed As Double
Console.WriteLine("IsNumeric(""" & s & """) = " & IsNumeric(s).ToString().PadRight(5) & " Double.TryParse = " & Double.TryParse(s, parsed).ToString())
Next
Console.WriteLine("-- IsNumeric on non-strings")
Console.WriteLine(IsNumeric(5).ToString() & " " & IsNumeric(True).ToString() & " " & IsNumeric(#1/1/2026#).ToString() & " " & IsNumeric("5"c).ToString() & " " & IsNumeric(Nothing).ToString())
Console.WriteLine("-- TypeName, VarType, VbTypeName")
Dim values As Object() = {1, 2L, 3.5, 4.5F, 5D, "text", "c"c, True, #1/1/2026#, Nothing, New Integer() {1, 2}, New List(Of String)(), DBNull.Value, CByte(1)}
For Each v As Object In values
Console.WriteLine(TypeName(v).PadRight(16) & VarType(v).ToString().PadRight(10) & If(v Is Nothing, "(Nothing)", v.GetType().Name))
Next
Console.WriteLine("-- the Is functions")
Dim arr As Integer() = {10, 20, 30}
Console.WriteLine("IsArray " & IsArray(arr).ToString() & ", IsNothing " & IsNothing(Nothing).ToString() & ", IsDBNull " & IsDBNull(DBNull.Value).ToString() & ", IsReference " & IsReference("x").ToString() & "/" & IsReference(5).ToString() & ", IsError " & IsError(New ArgumentException()).ToString())
Console.WriteLine("LBound " & LBound(arr).ToString() & ", UBound " & UBound(arr).ToString())
Console.WriteLine("-- RGB and QBColor return BGR integers")
Console.WriteLine(Hex(RGB(255, 128, 0)) & " " & Hex(QBColor(12)))
Console.WriteLine(SystemTypeName("Integer") & " " & VbTypeName("Int32") & " " & SystemTypeName("Boolean"))
End Sub
End Module
-- IsNumeric accepts more than Double.TryParse
IsNumeric("42") = True Double.TryParse = True
IsNumeric(" 42 ") = True Double.TryParse = True
IsNumeric("-1.5") = True Double.TryParse = True
IsNumeric("1e3") = True Double.TryParse = True
IsNumeric("$12") = True Double.TryParse = False
IsNumeric("(5)") = True Double.TryParse = False
IsNumeric("&HFF") = True Double.TryParse = False
IsNumeric("&O17") = True Double.TryParse = False
IsNumeric("1,000") = True Double.TryParse = True
IsNumeric("12abc") = False Double.TryParse = False
IsNumeric("") = False Double.TryParse = False
-- IsNumeric on non-strings
True True False True False
-- TypeName, VarType, VbTypeName
Integer Integer Int32
Long Long Int64
Double Double Double
Single Single Single
Decimal Decimal Decimal
String String String
Char Char Char
Boolean Boolean Boolean
Date Date DateTime
Nothing Object (Nothing)
Integer() 8195 Int32[]
List(Of String) Object List`1
DBNull Null DBNull
Byte Byte Byte
-- the Is functions
IsArray True, IsNothing True, IsDBNull True, IsReference True/False, IsError True
LBound 0, UBound 2
-- RGB and QBColor return BGR integers
80FF FF
System.Int32 Integer System.Boolean
Source: Information module
-
IsNumericis much more permissive thanDouble.TryParse: it accepts currency symbols, parentheses for negatives, the&Hand&Oprefixes and surrounding spaces. It isTruefor"&HFF", whichDouble.Parserejects, and it says nothing about whether the value fits in the target type. It also treats aBooleanand aChardigit as numeric but not aDate.IsNumeric(Nothing)isFalse. UseTryParsewith an explicit culture andNumberStyles. -
TypeNamereturns the Visual Basic name (Integer,Date,Integer(),List(Of String)),VarTypereturns aVariantType(a VB6 code; an array adds 8192, so anInteger()is 8195) and falls back toObjectfor classes, andVbTypeName/SystemTypeNamemap between the VB names and the .NET names.GetType(...).Nameis the .NET name. -
IsArray,IsDBNull,IsReferenceandIsErrorare one-line tests that read well in old code;TypeOf x Is Tandx Is Nothingare the modern forms.IsNothing(x)is the function form ofx Is Nothing. -
LBoundandUBoundwork on any array;LBoundis always 0 in .NET.RGBandQBColorreturn a BGR integer (RGB(255, 128, 0)is&H0080FF), not the ARGB value ofColor.FromArgb.
The legacy file I/O in FileSystem
The FileSystem module of Microsoft.VisualBasic (not the FileIO.FileSystem class) is the VB6 file model: you open a file on a file number, then Print, Write, Input, LineInput, FileGet and FilePut on that number. It is not obsolete and it works on .NET,
but System.IO is the model for new code (see Files, Directories and Streams). The program exercises all four modes and the file-system helpers; the first line turns CA1416 off because Dir and Rename are annotated as Windows-only:
Option Strict On
#Disable Warning CA1416 ' Dir and Rename are annotated as Windows-only; this program runs on Linux too
Imports System.IO
Module LegacyFileTour
Sub Main()
Dim folder As String = Path.Combine(Path.GetTempPath(), "shelf-legacy-io")
If Directory.Exists(folder) Then Directory.Delete(folder, True)
MkDir(folder)
Dim textFile As String = Path.Combine(folder, "books.txt")
Console.WriteLine("-- report output: Print, PrintLine, TAB and SPC")
Dim n As Integer = FreeFile()
FileOpen(n, textFile, OpenMode.Output)
PrintLine(n, "Title", TAB(12), "Year")
PrintLine(n, "Dune", TAB(12), 1965)
Print(n, "no line end, ")
PrintLine(n, "then one", SPC(3), "x")
PrintLine(n, "a", "b", True)
FileClose(n)
Console.Write(File.ReadAllText(textFile))
Console.WriteLine("-- data output and input: WriteLine, Input, EOF")
Dim dataFile As String = Path.Combine(folder, "books.csv")
n = FreeFile()
FileOpen(n, dataFile, OpenMode.Output)
WriteLine(n, "Dune", 1965, True)
WriteLine(n, "Emma", 1815, False)
FileClose(n)
Console.WriteLine("line ends written by WriteLine: LF=" & File.ReadAllText(dataFile).Count(Function(c) c = vbLf).ToString() & " CR=" & File.ReadAllText(dataFile).Count(Function(c) c = vbCr).ToString())
' Input recognises CR and CRLF but not a lone LF, so give it a file with Windows line ends
File.WriteAllText(dataFile, File.ReadAllText(dataFile).Replace(vbLf, vbCrLf))
n = FreeFile()
FileOpen(n, dataFile, OpenMode.Input)
Do Until EOF(n)
Dim title As String = Nothing, year As Integer, inPrint As Boolean
Input(n, title)
Input(n, year)
Input(n, inPrint)
Console.WriteLine("read : " & title & ", " & year.ToString() & ", " & inPrint.ToString())
Loop
Console.WriteLine("EOF = " & EOF(n).ToString() & ", LOF = " & LOF(n).ToString() & " bytes")
FileClose(n)
Console.WriteLine("-- whole lines: LineInput")
n = FreeFile()
FileOpen(n, textFile, OpenMode.Input)
Dim lines As Integer = 0
Do Until EOF(n)
Dim line As String = LineInput(n)
lines += 1
If lines = 1 Then Console.WriteLine("first line : '" & line & "'")
Loop
Console.WriteLine("lines : " & lines.ToString())
FileClose(n)
Console.WriteLine("-- random access with a fixed-length record")
Dim recordFile As String = Path.Combine(folder, "books.dat")
Dim rec As Integer = FreeFile()
FileOpen(rec, recordFile, OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Default, 4)
FilePut(rec, 1965, 1)
FilePut(rec, 1815, 2)
FilePut(rec, 1922, 3)
Dim value As Integer
FileGet(rec, value, 2)
Console.WriteLine("record 2 : " & value.ToString() & ", records = " & (LOF(rec) \ 4).ToString())
FileClose(rec)
Console.WriteLine("-- binary access with Seek")
Dim bin As Integer = FreeFile()
FileOpen(bin, Path.Combine(folder, "bytes.bin"), OpenMode.Binary)
FilePut(bin, CByte(7))
FilePut(bin, 258S)
Seek(bin, 1)
Dim b As Byte, s As Short
FileGet(bin, b)
FileGet(bin, s)
Console.WriteLine("read back : " & b.ToString() & ", " & s.ToString() & ", position = " & Seek(bin).ToString())
FileClose(bin)
Console.WriteLine("-- the file-system helpers")
FileCopy(textFile, Path.Combine(folder, "copy.txt"))
Try
Rename(Path.Combine(folder, "copy.txt"), Path.Combine(folder, "backup.txt"))
Catch ex As PlatformNotSupportedException
Console.WriteLine("Rename : " & ex.GetType().Name & ": " & ex.Message)
File.Move(Path.Combine(folder, "copy.txt"), Path.Combine(folder, "backup.txt"))
End Try
Console.WriteLine("FileLen : " & FileLen(textFile).ToString() & " bytes")
Console.WriteLine("GetAttr : " & GetAttr(textFile).ToString())
Dim names As New List(Of String)()
Dim found As String = Dir(Path.Combine(folder, "*.txt"))
Do While found <> ""
names.Add(found)
found = Dir()
Loop
names.Sort()
Console.WriteLine("Dir : " & String.Join(", ", names))
Kill(Path.Combine(folder, "backup.txt"))
Console.WriteLine("after Kill : " & Directory.GetFiles(folder).Length.ToString() & " files")
Directory.Delete(folder, True)
End Sub
End Module
-- report output: Print, PrintLine, TAB and SPC
Title Year
Dune 1965
no line end, then one x
a b True
-- data output and input: WriteLine, Input, EOF
line ends written by WriteLine: LF=2 CR=0
read : Dune, 1965, True
read : Emma, 1815, False
EOF = True, LOF = 41 bytes
-- whole lines: LineInput
first line : 'Title Year'
lines : 4
-- random access with a fixed-length record
record 2 : 1815, records = 3
-- binary access with Seek
read back : 7, 258, position = 4
-- the file-system helpers
Rename : PlatformNotSupportedException: Operation is not supported on this platform.
FileLen : 93 bytes
GetAttr : Normal
Dir : backup.txt, books.txt
after Kill : 4 files
Source: FileSystem module
-
Print/PrintLineare for reports: items are separated into 14-character print zones (thea b Trueline),TAB(n)moves to a column,SPC(n)inserts spaces.Write/WriteLinewrite data: strings in quotes, booleans as#TRUE#, items separated by commas, whichInputreads back. -
InputrecognisesCRandCRLFas the end of a line, not a loneLF.WriteLinewroteLFonly on Linux (the program counts 2LFand noCR), and a first version of the program that read it straight back failed withInvalidCastException: Conversion from string ... to type 'Boolean' is not valid. The program therefore rewrites the file withvbCrLfbefore reading it.LineInputandEOFcoped with theLFfile. -
Random-access files use a record length given in
FileOpen;FilePut(n, value, recordNumber)andFileGetare one-based in record numbers andLOFis in bytes. The first draft of the example opened the file with record length 8 for 4-byte integers andLOF \ 8gave 2 records instead of 3, so keep the record length equal to the data. -
Binary mode uses
Seek(one-based position). Fixed-length strings needVBFixedString. -
RenamethrewPlatformNotSupportedExceptionon Linux, so the program falls back toFile.Move.Dirwith a pattern and thenDir()with no arguments returns the next match,""at the end; the sort in the program is only to make the output order stable. -
FileOpen(..., OpenMode.Output)truncates;OpenMode.Appendappends; theOpenAccessandOpenShareenumerations give the access and the locking. A forgottenFileClosekeeps the file locked until the process exits. -
The
FilePutoverload that takes anObjectis obsolete (see below); write a single value withFilePutObjector giveFilePuta typed variable.
Financial and VBMath
The Financial module has the Excel-style time-value-of-money functions; VBMath has Rnd and Randomize. (Rounding, Decimal and the other numeric topics are on Numbers and Math.)
Option Strict On
Module FinancialMathTour
Sub Main()
Console.WriteLine("-- loan and annuity functions (negative = money paid out)")
Dim payment As Double = Pmt(0.05 / 12, 60, 20000)
Console.WriteLine("Pmt : " & payment.ToString("F2"))
Console.WriteLine("IPmt : " & IPmt(0.05 / 12, 1, 60, 20000).ToString("F2") & ", PPmt: " & PPmt(0.05 / 12, 1, 60, 20000).ToString("F2"))
Console.WriteLine("FV : " & FV(0.04 / 12, 120, -100).ToString("F2"))
Console.WriteLine("PV : " & PV(0.05 / 12, 60, -377.42).ToString("F2"))
Console.WriteLine("NPer : " & NPer(0.05 / 12, -377.42, 20000).ToString("F1"))
Console.WriteLine("Rate : " & (Rate(60, -377.42, 20000) * 12).ToString("P2"))
Console.WriteLine("-- cash-flow functions")
Dim flows As Double() = {-1000, 300, 400, 500}
Console.WriteLine("NPV : " & NPV(0.1, flows).ToString("F2") & " (the first value is discounted too)")
Console.WriteLine("IRR : " & IRR(flows).ToString("P2"))
Console.WriteLine("MIRR : " & MIRR(flows, 0.08, 0.1).ToString("P2"))
Console.WriteLine("-- depreciation")
Console.WriteLine("SLN : " & SLN(10000, 1000, 5).ToString("F2"))
Console.WriteLine("SYD : " & SYD(10000, 1000, 5, 1).ToString("F2"))
Console.WriteLine("DDB : " & DDB(10000, 1000, 5, 1).ToString("F2") & ", year 2: " & DDB(10000, 1000, 5, 2).ToString("F2"))
Console.WriteLine("-- VBMath: Rnd and Randomize")
Rnd(-1)
Randomize(42)
Dim a As Single = Rnd()
Dim b As Single = Rnd()
Rnd(-1)
Randomize(42)
Console.WriteLine("same seed gives the same sequence: " & (a = Rnd() AndAlso b = Rnd()).ToString())
Console.WriteLine("range 0 <= Rnd() < 1: " & (a >= 0.0F AndAlso a < 1.0F).ToString())
Console.WriteLine("Rnd(0) repeats the last value: " & (Rnd(0) = Rnd(0)).ToString())
Dim dice As Integer = CInt(Int(Rnd() * 6)) + 1
Console.WriteLine("dice between 1 and 6: " & (dice >= 1 AndAlso dice <= 6).ToString())
End Sub
End Module
-- loan and annuity functions (negative = money paid out)
Pmt : -377.42
IPmt : -83.33, PPmt: -294.09
FV : 14724.98
PV : 19999.75
NPer : 60.0
Rate : 5.00 %
-- cash-flow functions
NPV : -19.12 (the first value is discounted too)
IRR : 8.90 %
MIRR : 9.22 %
-- depreciation
SLN : 1800.00
SYD : 3000.00
DDB : 4000.00, year 2: 2400.00
-- VBMath: Rnd and Randomize
same seed gives the same sequence: True
range 0 <= Rnd() < 1: True
Rnd(0) repeats the last value: True
dice between 1 and 6: True
Source: Financial module
-
The sign convention is the Excel one: money you pay is negative (
Pmtis -377.42 for a 20,000 loan), money you receive is positive. Mixing the signs gives silently wrong answers or an exception fromIRR. -
The rate and the number of periods must use the same unit (
0.05 / 12with 60 months). The functions work inDouble; do not use them to post amounts to a ledger, useDecimaland round once. -
NPVdiscounts every value from the first period, so the initial investment (period 0) is usually added outside the call.IRRstarts from a guess and can fail to converge. -
DDB,SLNandSYDare three depreciation methods;DDBtakes an optional factor (2 means double-declining). -
Rndreturns aSinglein [0, 1). The recipe for repeatable numbers isRnd(-1)followed byRandomize(seed), as in the program; withoutRandomizethe sequence is the same in every process: a separate check printed0.7055475for the firstRnd()in two different runs, so a program that forgetsRandomizerepeats itself.Rnd(0)returns the last value again.Rndis not suitable for anything that must be unpredictable or fair: useRandom.SharedorRandomNumberGenerator.
ErrObject
Err is a global ErrObject that VB6 used for error handling. In structured code it is still there: after an exception is caught, Err describes it. It also provides Err.Raise, which throws.
Option Strict On
Module ErrTour
Sub Main()
Console.WriteLine("-- Err is a global object that mirrors the last exception")
Try
Dim zero As Integer = 0
Console.WriteLine(10 \ zero)
Catch ex As DivideByZeroException
Console.WriteLine("Err.Number : " & Err.Number.ToString())
Console.WriteLine("Err.Description : " & Err.Description)
Console.WriteLine("Err.Source : " & Err.Source)
Console.WriteLine("GetException is the same object: " & Object.ReferenceEquals(Err.GetException(), ex).ToString())
Err.Clear()
Console.WriteLine("after Clear : " & Err.Number.ToString() & " '" & Err.Description & "'")
End Try
Console.WriteLine("-- Err.Raise throws an exception that Try can catch")
Try
Err.Raise(vbObjectError + 1000, "ShelfApp", "The shelf is full")
Catch ex As Exception
Console.WriteLine(ex.GetType().Name & ": " & ex.Message & " (Err.Number = " & (Err.Number - vbObjectError).ToString() & " + vbObjectError, Source = " & Err.Source & ")")
End Try
Try
Err.Raise(5)
Catch ex As Exception
Console.WriteLine(ex.GetType().Name & ": " & ex.Message)
End Try
Try
Err.Raise(53)
Catch ex As Exception
Console.WriteLine(ex.GetType().Name & ": " & ex.Message)
End Try
Console.WriteLine("-- Err.Number for other exceptions")
Dim samples As New List(Of Exception) From {
New InvalidCastException(), New OverflowException(), New IndexOutOfRangeException(), New NullReferenceException(),
New IO.FileNotFoundException(), New FormatException(), New ArgumentException(), New OutOfMemoryException()
}
For Each ex As Exception In samples
Try
Throw ex
Catch caught As Exception
Console.WriteLine(caught.GetType().Name.PadRight(26) & Err.Number.ToString().PadLeft(6) & " " & Err.Description)
End Try
Next
End Sub
End Module
-- Err is a global object that mirrors the last exception
Err.Number : 11
Err.Description : Attempted to divide by zero.
Err.Source : System.Private.CoreLib
GetException is the same object: True
after Clear : 0 ''
-- Err.Raise throws an exception that Try can catch
Exception: The shelf is full (Err.Number = 1000 + vbObjectError, Source = ShelfApp)
ArgumentException: Procedure call or argument is not valid.
FileNotFoundException: File not found.
-- Err.Number for other exceptions
InvalidCastException 13 Specified cast is not valid.
OverflowException 6 Arithmetic operation resulted in an overflow.
IndexOutOfRangeException 9 Index was outside the bounds of the array.
NullReferenceException 91 Object reference not set to an instance of an object.
FileNotFoundException 53 Unable to find the specified file.
FormatException 13 One of the identified items was in an invalid format.
ArgumentException 5 Value does not fall within the expected range.
OutOfMemoryException 7 Insufficient memory to continue the execution of the program.
Source: ErrObject class
-
Err.Numbermaps .NET exceptions to the classic VB6 numbers (11 division by zero, 13 type mismatch, 6 overflow, 9 subscript out of range, 91 object variable not set, 53 file not found, 5 invalid procedure call, 7 out of memory).FormatExceptionandInvalidCastExceptionboth map to 13. -
Err.GetException()returns the real exception object, soErradds nothing thatCatch exdoes not give; use the exception. -
Err.Raise(number, source, description)throws a plainExceptionfor a custom number (the example usesvbObjectError + 1000) and a typed exception for known numbers (Err.Raise(5)throwsArgumentException,Err.Raise(53)throwsFileNotFoundException). A custom exception class is clearer. -
The unstructured error-handling statements that fill
Errare covered on Unstructured Error Handling: On Error; structured exceptions are on Structured Exception Handling.
Collection
The VB6 Collection stores Object items, is one-based, and can be addressed by position or by a case-insensitive string key; Add can place an item Before or After another.
Option Strict On
Module CollectionTour
Sub Main()
Dim shelf As New Collection()
shelf.Add("Dune", "dune")
shelf.Add("Emma", "emma")
shelf.Add("Ulysses")
shelf.Add("Beloved", "beloved", Before:=1)
shelf.Add("Ivanhoe", "ivanhoe", After:=2)
Console.WriteLine("-- one-based, ordered by Before and After")
For i As Integer = 1 To shelf.Count
Console.Write(i.ToString() & "=" & CStr(shelf(i)) & " ")
Next
Console.WriteLine()
Console.WriteLine("-- keys are case-insensitive")
Console.WriteLine(CStr(shelf("DUNE")) & ", Contains: " & shelf.Contains("emma").ToString() & "/" & shelf.Contains("zzz").ToString())
Console.WriteLine("-- items are Object, For Each yields Object")
For Each item As Object In shelf
Console.Write(item.ToString() & ";")
Next
Console.WriteLine()
Console.WriteLine("-- errors")
Try
shelf.Add("Duplicate", "dune")
Catch ex As ArgumentException
Console.WriteLine("add duplicate key : " & ex.GetType().Name & ": " & ex.Message)
End Try
Try
Console.WriteLine(shelf(0))
Catch ex As IndexOutOfRangeException
Console.WriteLine("index 0 : " & ex.GetType().Name & ": " & ex.Message)
End Try
Try
Console.WriteLine(shelf("zzz"))
Catch ex As ArgumentException
Console.WriteLine("missing key : " & ex.GetType().Name & ": " & ex.Message)
End Try
shelf.Remove("emma")
shelf.Remove(1)
Console.WriteLine("after Remove : " & shelf.Count.ToString())
Console.WriteLine("-- the generic replacements")
Dim titles As New List(Of String) From {"Dune", "Emma"}
Dim byKey As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase) From {{"dune", "Dune"}, {"emma", "Emma"}}
Console.WriteLine(titles(0) & " " & byKey("EMMA") & " " & byKey.ContainsKey("Dune").ToString())
End Sub
End Module
-- one-based, ordered by Before and After
1=Beloved 2=Dune 3=Ivanhoe 4=Emma 5=Ulysses
-- keys are case-insensitive
Dune, Contains: True/False
-- items are Object, For Each yields Object
Beloved;Dune;Ivanhoe;Emma;Ulysses;
-- errors
add duplicate key : ArgumentException: Add failed. Duplicate key value supplied.
index 0 : IndexOutOfRangeException: Collection index must be in the range 1 to the size of the collection.
missing key : ArgumentException: Argument 'Index' is not a valid value. (Parameter 'Key')
after Remove : 3
-- the generic replacements
Dune Emma True
Source: Collection class
It is not a List and it is not a Dictionary: the items are untyped (casts everywhere), indexing is one-based, the same object answers to a number and to a key, and an invalid index throws IndexOutOfRangeException while a missing key throws ArgumentException.
Use List(Of T) for sequences and Dictionary(Of TKey, TValue) for keyed access (see Collections); keep Collection for code that has to match old behaviour, and in the compatibility shims of a migration
(see Migrating Legacy Visual Basic).
Constants and ControlChars
Constants holds vbCrLf, vbTab, vbTrue, vbObjectError and a copy of the members of the VB enumerations (vbYes, vbBinaryCompare, vbMonday, vbString …). ControlChars has the same characters as Char or String fields.
Option Strict On
Module ConstantsTour
Private Function Codes(text As String) As String
Return String.Join(" ", text.Select(Function(c) AscW(c).ToString()))
End Function
Sub Main()
Console.WriteLine("-- line and character constants (character codes)")
Console.WriteLine("vbCrLf : " & Codes(vbCrLf))
Console.WriteLine("vbCr, vbLf : " & Codes(vbCr) & ", " & Codes(vbLf))
Console.WriteLine("vbTab, vbBack : " & Codes(vbTab) & ", " & Codes(vbBack))
Console.WriteLine("vbFormFeed, vbVT : " & Codes(vbFormFeed) & ", " & Codes(vbVerticalTab))
Console.WriteLine("vbNullChar : " & Codes(vbNullChar))
Console.WriteLine("Environment.NewLine here : " & Codes(Environment.NewLine))
Console.WriteLine("ControlChars.NewLine here: " & Codes(ControlChars.NewLine))
Console.WriteLine("ControlChars.CrLf : " & Codes(ControlChars.CrLf))
Console.WriteLine("ControlChars.Quote : " & AscW(ControlChars.Quote).ToString() & " (a Char)")
Console.WriteLine("-- vbNullString is Nothing, not an empty string")
Console.WriteLine((vbNullString Is Nothing).ToString() & " " & (vbNullString = "").ToString() & " " & Len(vbNullString).ToString())
Console.WriteLine("-- numeric constants")
Console.WriteLine("vbTrue " & vbTrue.ToString() & ", vbFalse " & vbFalse.ToString() & ", vbObjectError " & vbObjectError.ToString())
Console.WriteLine("vbBinaryCompare " & CInt(vbBinaryCompare).ToString() & ", vbTextCompare " & CInt(vbTextCompare).ToString())
Console.WriteLine("vbSunday " & CInt(vbSunday).ToString() & ", vbMonday " & CInt(vbMonday).ToString() & ", vbUseSystemDayOfWeek " & CInt(vbUseSystemDayOfWeek).ToString())
Console.WriteLine("-- MsgBox style and result constants combine as flags")
Dim style As MsgBoxStyle = MsgBoxStyle.YesNo Or MsgBoxStyle.Question Or MsgBoxStyle.DefaultButton2
Console.WriteLine("YesNo Or Question Or DefaultButton2 = " & CInt(style).ToString() & " (" & style.ToString() & ")")
Console.WriteLine("vbYes " & CInt(vbYes).ToString() & ", vbNo " & CInt(vbNo).ToString() & ", vbOK " & CInt(vbOK).ToString() & ", vbCancel " & CInt(vbCancel).ToString())
Console.WriteLine("-- VarType values")
Console.WriteLine("vbInteger " & CInt(vbInteger).ToString() & ", vbString " & CInt(vbString).ToString() & ", vbArray " & CInt(vbArray).ToString() & ", vbObject " & CInt(vbObject).ToString())
End Sub
End Module
-- line and character constants (character codes)
vbCrLf : 13 10
vbCr, vbLf : 13, 10
vbTab, vbBack : 9, 8
vbFormFeed, vbVT : 12, 11
vbNullChar : 0
Environment.NewLine here : 10
ControlChars.NewLine here: 13 10
ControlChars.CrLf : 13 10
ControlChars.Quote : 34 (a Char)
-- vbNullString is Nothing, not an empty string
True True 0
-- numeric constants
vbTrue True, vbFalse False, vbObjectError -2147221504
vbBinaryCompare 0, vbTextCompare 1
vbSunday 1, vbMonday 2, vbUseSystemDayOfWeek 0
-- MsgBox style and result constants combine as flags
YesNo Or Question Or DefaultButton2 = 292 (YesNo, Question, DefaultButton2)
vbYes 6, vbNo 7, vbOK 1, vbCancel 2
-- VarType values
vbInteger 3, vbString 8, vbArray 8192, vbObject 9
Source: Constants module, ControlChars class
-
vbCrLf,vbCr,vbLf,vbTabandControlChars.CrLfare fixed characters.ControlChars.NewLineis also fixed CR LF (printed as 13 10) even though its name suggests the platform’s line end: on LinuxEnvironment.NewLineisLF(10) only. UseEnvironment.NewLinefor text that should follow the platform andvbCrLfwhere the protocol or file format demands CR LF. -
vbNullStringisNothingyet compares equal to"", and hasLen0;vbNullCharis the character 0 (used with API calls). -
vbTrueandvbFalseareTriStatevalues and print asTrue/False; the numeric value of True is -1 in Visual Basic (CInt(True)); C# has no implicit conversion fromboolto an integer. -
The result and style constants (
vbYes,vbYesNo,vbQuestion,vbDefaultButton2) areMsgBoxStyle/MsgBoxResultvalues that combine withOr. They only make sense withMsgBox. -
Obsolete:
vbNewLineis marked obsolete: the compiler reports BC40000 with the text shown next. TheFilePutoverload with anObjectparameter is obsolete too (the message recommendsFilePutObject); passing anObjectvariable toFilePuton this SDK gaveerror BC30518: Overload resolution failed because no accessible 'FilePut' can be called with these arguments.
The program below (built with TreatWarningsAsErrors set to false, so the warnings are only warnings) triggers the obsolete constant and two Windows-only annotations:
Option Strict On
Module Program
Sub Main()
Dim line As String = "Dune" & vbNewLine
Dim n As Integer = FreeFile()
Dim value As Object = 42
FileOpen(n, "/tmp/x.dat", OpenMode.Binary)
FilePutObject(n, value)
FileClose(n)
Console.WriteLine(StrConv("dune", VbStrConv.ProperCase))
Beep()
Console.WriteLine(line.Length.ToString())
End Sub
End Module
Program.vb(5,39): warning BC40000: 'Public Const vbNewLine As String' is obsolete: 'vbNewLine has been deprecated. For a carriage return and line feed, use vbCrLf. For the current platform's newline, use System.Environment.NewLine.'.
Program.vb(11,27): warning CA1416: This call site is reachable on all platforms. 'Public Overloads Function StrConv(str As String, Conversion As VbStrConv, [LocaleID As Integer = 0]) As String' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
Program.vb(12,9): warning CA1416: This call site is reachable on all platforms. 'Public Overloads Sub Beep()' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
Enumerations of the library
| Enumeration | Used by |
|---|---|
|
the |
|
|
|
|
|
|
|
the formatting functions, |
|
|
CompilerServices: code you do not write
The 29 public types of Microsoft.VisualBasic.CompilerServices are called by the compiler: Conversions, Operators, LikeOperator, NewLateBinding, ObjectFlowControl, StaticLocalInitFlag, Versioned, Utils, ProjectData, StandardModuleAttribute,
OptionCompareAttribute and the ...Type helper classes. They are public because the generated code has to call them from your assembly. They are hidden from IntelliSense and not part of the supported surface, but nothing stops you calling them.
Reading the IL of five methods shows which helper each construct becomes:
Option Strict On
Imports System.ComponentModel
Imports System.Reflection
Imports System.Reflection.Emit
Imports System.Runtime.CompilerServices
' Four small methods whose compiled bodies we will inspect
Public NotInheritable Class Probe
Public Shared Function Matches(text As String, pattern As String) As Boolean
Return text Like pattern
End Function
Public Shared Function Same(a As String, b As String) As Boolean
Return a = b
End Function
Public Shared Function ToInt(value As Object) As Integer
Return CInt(value)
End Function
Public Shared Function Shorten(text As String) As String
Return Left(text, 3) & Trim(text)
End Function
Public Shared Function Describe(value As Object) As String
Return TypeName(value) & Len(CStr(value)).ToString()
End Function
End Class
Module CompilerServicesTour
' Lists the methods called by a method body by scanning its IL for call opcodes
Private Function CalledMethods(m As MethodInfo) As List(Of String)
Dim result As New List(Of String)()
Dim il As Byte() = m.GetMethodBody().GetILAsByteArray()
For i As Integer = 0 To il.Length - 5
If il(i) = &H28 OrElse il(i) = &H6F Then
Dim token As Integer = BitConverter.ToInt32(il, i + 1)
Dim table As Integer = (token >> 24) And &HFF
If table = &H6 OrElse table = &HA OrElse table = &H2B Then
Try
Dim target As MethodBase = m.Module.ResolveMethod(token)
result.Add(target.DeclaringType.Name & "." & target.Name)
i += 4
Catch ex As ArgumentException
End Try
End If
End If
Next
Return result
End Function
Sub Main()
For Each name As String In {"Matches", "Same", "ToInt", "Shorten", "Describe"}
Dim m As MethodInfo = GetType(Probe).GetMethod(name)
Console.WriteLine(name.PadRight(10) & String.Join(", ", CalledMethods(m)))
Next
Console.WriteLine("-- who may call the helper classes")
Dim asm As Assembly = GetType(Microsoft.VisualBasic.CompilerServices.Conversions).Assembly
Dim hidden As Integer = 0, total As Integer = 0
For Each t As Type In asm.GetExportedTypes()
If t.Namespace = "Microsoft.VisualBasic.CompilerServices" Then
total += 1
Dim eb = t.GetCustomAttribute(Of EditorBrowsableAttribute)()
If eb IsNot Nothing AndAlso eb.State = EditorBrowsableState.Never Then hidden += 1
End If
Next
Console.WriteLine(hidden.ToString() & " of " & total.ToString() & " public types in CompilerServices are hidden from IntelliSense")
Console.WriteLine("Conversions.ToInteger(""12"") still works: " & Microsoft.VisualBasic.CompilerServices.Conversions.ToInteger("12").ToString())
End Sub
End Module
Matches LikeOperator.LikeString
Same Operators.CompareString
ToInt Conversions.ToInteger
Shorten Strings.Left, Strings.Trim, String.Concat
Describe RuntimeHelpers.GetObjectValue, Versioned.TypeName, Conversions.ToString, Strings.Len, Int32.ToString, String.Concat
-- who may call the helper classes
29 of 29 public types in CompilerServices are hidden from IntelliSense
Conversions.ToInteger("12") still works: 12
Source: StandardModuleAttribute
-
LikeisLikeOperator.LikeString, and=on strings isOperators.CompareString(which is whyOption Compare Textchanges it);CIntof anObjectisConversions.ToInteger. -
Left,TrimandLenare ordinary calls into theStringsmodule, so they cost a method call and an argument check whereSubstringcosts a method call. -
Versioned.TypeNameis what theTypeNamefunction calls, andRuntimeHelpers.GetObjectValueappears around anObjectargument to preserve value-type semantics. -
The program scans for
call/callvirtopcodes and resolves their tokens; it is a demonstration, not a disassembler. Useildasm, ILSpy or SharpLab for exact IL. -
Do not call these helpers yourself: their signatures and behaviour can change without notice,
NewLateBindingis why late binding is slow, and theFallback...members are marked obsolete.
Microsoft.VisualBasic.Compatibility.VB6
On .NET Framework a separate assembly, Microsoft.VisualBasic.Compatibility, offered the VB6 migration helpers (Microsoft.VisualBasic.Compatibility.VB6: control arrays, font helpers, Support functions used by the Upgrade Wizard). It is a .NET Framework component only.
Option Strict On
Imports System.IO
Imports System.Reflection
Module CompatTour
Sub Main()
Dim core As Assembly = GetType(Microsoft.VisualBasic.Strings).Assembly
Dim namespaces As List(Of String) = core.GetExportedTypes().Select(Function(t) If(t.Namespace, "")).Distinct().OrderBy(Function(n) n).ToList()
Console.WriteLine("Namespaces in " & core.GetName().Name & ":")
For Each ns As String In namespaces
Console.WriteLine(" " & ns)
Next
Console.WriteLine("Any namespace with 'Compatibility': " & namespaces.Any(Function(n) n.Contains("Compatibility")).ToString())
Console.WriteLine("Type found by name: " & (Type.GetType("Microsoft.VisualBasic.Compatibility.VB6.Support, Microsoft.VisualBasic.Compatibility") IsNot Nothing).ToString())
Try
Assembly.Load("Microsoft.VisualBasic.Compatibility")
Catch ex As FileNotFoundException
Console.WriteLine(ex.GetType().Name & ": " & ex.Message.TrimEnd())
End Try
Console.WriteLine("Runtime assemblies named Microsoft.VisualBasic*:")
For Each f As String In Directory.GetFiles(Path.GetDirectoryName(GetType(Object).Assembly.Location), "Microsoft.VisualBasic*.dll").OrderBy(Function(x) x)
Console.WriteLine(" " & Path.GetFileName(f))
Next
End Sub
End Module
Namespaces in Microsoft.VisualBasic.Core:
Microsoft.VisualBasic
Microsoft.VisualBasic.CompilerServices
Microsoft.VisualBasic.FileIO
Any namespace with 'Compatibility': False
Type found by name: False
FileNotFoundException: Could not load file or assembly 'Microsoft.VisualBasic.Compatibility, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
Runtime assemblies named Microsoft.VisualBasic*:
Microsoft.VisualBasic.Core.dll
Microsoft.VisualBasic.dll
The runtime that ships with .NET has no such namespace or assembly. Code that uses it must be rewritten to ordinary Windows Forms or WPF code; see Migrating Legacy Visual Basic and The VB Family: VB6, VBA and VBScript.
When to prefer the BCL
| Runtime library | BCL | Reason to choose the BCL |
|---|---|---|
|
|
zero-based like the rest of .NET, culture and comparison explicit; but the VB functions never throw for a too-long length |
|
|
the culture is explicit |
|
interpolation with format strings, |
culture and format are visible |
|
|
no leading space, culture explicit |
|
|
no guessing |
|
|
reads the same in every .NET language |
|
|
no boundary-count surprise |
|
|
testable clock |
|
|
encodings, async, |
|
|
typed and zero-based |
|
exceptions |
typed, stack traces |
|
|
cross-platform, arguments preserved |
|
|
no hidden Windows Forms dependency in the call |
|
|
quality, thread safety |
|
|
only the needed branch is evaluated |
|
none in the BCL |
keep the VB functions, in |
The VB functions remain good when you port VB6 or VBA logic unchanged, when you need the VB-specific behaviour on purpose (tolerance of Nothing, clipping), or when brevity matters in a throw-away script.
Differences from C#
-
C# has no equivalent keywords: every function above is called as
Strings.Left(...),Interaction.Choose(...),Financial.Pmt(...)after addingusing Microsoft.VisualBasic;(the reference is already available in .NET projects). CallingFileSystem.FileOpenfrom C# works and is used when reading legacy files. -
Type conversion keywords (
CInt,CType) are language features in Visual Basic and have no C# form;Convert.ToInt32and casts differ in rounding and in the way strings are parsed. -
vbCrLfand the other constants have no C# counterpart; C# uses the escape sequences"\r\n". -
C# compares strings with
==ordinally, while Visual Basic’s=followsOption Compare; the library functions that have aCompareargument follow it as well. -
See Strings and Text (C#) and C# and .NET for the other side.
Where the books are outdated
| Book habit | Today |
|---|---|
|
obsolete (BC40000); use |
|
obsolete; use |
|
throw |
|
throws on Linux; |
|
Windows registry only; use JSON or |
|
not available on .NET |
|
|
Treating |
predictable; use |
unstructured error handling plus |
|
Diagnostics reference
| Diagnostic | Meaning |
|---|---|
BC40000 |
use of an obsolete member ( |
BC30109 |
a class name used as an expression, for example |
BC30518 |
overload resolution failed, for example |
BC30057 |
too many arguments to a library function |
CA1416 |
the call is annotated as Windows-only and is reachable on other platforms (an error under |
Pitfalls checklist
-
Positions in the VB string functions are one-based; in the BCL they are zero-based.
-
Trimremoves spaces only;Replacewith a start argument drops the prefix;Stradds a leading space;ValandIsNumericaccept formats thatTryParserejects. -
ChooseandInteraction.Switchevaluate all arguments; refer toInteraction.Switchexplicitly. -
DateSerialandDateAddoverflow quietly;DateDiffcounts boundaries. -
ControlChars.NewLineis CR LF on every platform;Environment.NewLinefollows the platform. -
The legacy
Inputneeds CR or CR LF line ends. -
A Windows-only annotation (CA1416) is a build error under
TreatWarningsAsErrors; guard withOperatingSystem.IsWindows()or avoid the call. -
Do not use
Rnd,IsNumericorCallByNamewhere unpredictability, strictness or trimming matter. -
Do not call
Microsoft.VisualBasic.CompilerServicesdirectly.
References
-
Microsoft.VisualBasic namespace (API browser) with the module pages Strings, Conversion, DateAndTime, Interaction, Information, FileSystem, Financial and VBMath
-
Collection, ErrObject, Constants, ControlChars and Microsoft.VisualBasic.CompilerServices
-
Microsoft.VisualBasic.FileIO and Microsoft.VisualBasic.Compatibility.VB6
-
Strings and Text, Type Conversions, The My Namespace and Files, Directories and Streams in this section