Mixing Visual Basic and C#
Prerequisites: Namespaces, projects, and NuGet
Visual Basic and C# compile to the same IL, so a solution can contain projects in both languages that reference each other freely. This is the most common way teams modernize VB applications: keep the working VB code, and write new libraries in C# (or the reverse).
A C# library used from VB
dotnet new classlib -lang C# -o Pricing
dotnet new console -lang VB -o App
dotnet add App reference Pricing
// Pricing/Calculator.cs (C#)
namespace Pricing;
public static class Calculator
{
public static decimal WithTax(decimal net, decimal rate = 0.2m) => net * (1 + rate);
}
public record Product(string Name, decimal Price);
' illustrative: App/Program.vb, referencing the C# Pricing project
Imports Pricing
Module Program
Sub Main()
Console.WriteLine(Calculator.WithTax(100D))
Console.WriteLine(Calculator.WithTax(100D, rate:=0.1D))
Dim tea As New Product("Tea", 3.5D)
Console.WriteLine(tea)
Console.WriteLine(tea.Name)
End Sub
End Module
120.0
110.0
Product { Name = Tea, Price = 3.5 }
Tea
Static classes appear as modules, C# optional parameters work with VB named arguments, and C# records are ordinary classes to VB (VB can use them, but can't declare them).
Things to watch for
- Case sensitivity — C# allows two public members that differ only
in case (
Valueandvalue); VB can't tell them apart. Mark shared libraries[assembly: CLSCompliant(true)]to get warnings. - Newer C# features — some can't be used from VB. For example,
ref structtypes such asSpan(Of T)are rejected:Dim s As Span(Of Integer)gives error BC30668, "Types with embedded references are not supported in this version of your compiler". Keep public APIs meant for VB callers to ordinary classes, arrays, and interfaces. - Nullable annotations from C# (
string?) are ignored by VB. - Events and delegates interoperate fully; VB's
Handlesworks on C# events.
Converting code
Online and IDE converters (for example, the open-source
CodeConverter extension for Visual Studio) translate VB to C# and
back. They handle most syntax, but always review the result — VB-only
behaviors like Integer division with \, CInt rounding, and
case-insensitive comparisons (Option Compare Text) need care.
Rules of thumb
- New shared libraries: C# is the safer choice for long-term tooling and framework support.
- Existing, working VB code: keep it, add tests, and extend it in VB or alongside C# projects.
- Keep the boundary simple: plain classes, interfaces, and
Tasks work perfectly across languages.