UGTS Document #71 - Last Modified: 8/29/2015 3:23 PM
Migrating code from VB.NET to C#
VB.NET and C# are very similar languages, because they both use the same .NET Framework and
for the most part the merely use different syntax to express the same things. Even so, it
can be daunting to convert a large project from one language to the other in a short amount of time.
SharpDevelop is a useful tool which can greatly speed up this process. You can load a single file
or an entire project and convert all the code from VB.NET to C#. There are some limitations however:
- Web Projects - Visual Web Developer projects aren't supported by SharpDevelop.
You can't load an entire website and convert it at once.
- Form Designer Code - SharpDevelop will convert all the code in a windows form class, but it will
do so in a way that break the ability to load the form in the form designer.
- Imperfect Translation - SharpDevelop handles some
language elements badly, such as the conditional assignment operator,
declaring variables as var vs. dynamic, etc...
- Language Differences - VB.NET and C# are closely
related in capabilities, but there are some intentional differences
between the two. C# is designed to be stricter and more exact than
VB. Some things which are easy to do in VB are not so easy to do,
or are discouraged, in C#.
Here is a procedure can handle the translation as quickly as possible:
- Core Class Library Projects - if you have core
class library projects which are used by other projects, convert those
first. Visual Studio has no problem having a solution where some
projects use VB.NET and others use C# - it will compile each to its own
assembly and link them together without problems. For each project
you convert, create a new directory side by side with the old one, named
something like [Project][N], where N is the next major revision number
of your project. Convert the entire project in SharpDevelop and
save the new project to the new folder.
- Var / Dynamic - Search / Replace all instances of
the word 'dynamic' with 'var' (do this replacement one at a time to make
sure that you don't inadvertently replace this in comments or text).
Later you can go back and change the variables which really ought to be
dynamic (there are usually only a small fraction in your project).
- Namespace Importing - Unlike VB.NET, C# files must
explicitly declare the list of namespaces that are used / imported in
each file, there is no project-wide setting for namespaces to import in
each file. Therefore, it will probably be fastest to create a code
file which has the project wide using statements that every file should
have, and then copy/paste this into each converted C# file in your
project. This list should include the namespace
'Microsoft.VisualBasic' initiallly to ease the transition. Later
you can re-work your code to remove this.
- No Global Methods - Unlike VB.NET, if you define a
static method or member in a static module, you have to fully reference
the name with the module name to access it. In VB.NET, all you
have to do is call the function by name. This means that you might
need to go through the code to fully qualify some method or properties
that you are accessing.
- No DateTime Literals - In VB.NET you can define
literal date time values using the #...# syntax. That doesn't
exist in C#. If you only need a date literal in order to compare
two dates, sometimes you can instead get the Year of the date and do an
integer comparison instead. If this isn't enough, you could have a
property which returns the date literal value, and this property could
get the date value by creating it dynamically from a string.
- Conditional Assignment Operator - SharpDevelop has
a bug / deficiency that it will convert the If() function to the (a ? b
: c) conditional assignment operator, but it leaves out the outer
parenthesis. This is difficult to catch because it doesn't always
cause a compile time error, but it often changes the way the code works
due to operator precedence.
The only way to fix this is to go through every instance where you use
conditional assignment and make sure it the converted code is correct.
- Functions, Properties, and Indexers - VB.NET is
lenient / lazy / permissive when it comes to functions and properties,
whereas C# is much more rigid. In C#, properties cannot have
arguments. If you have such a property, in C# you must either
convert it into a function / method or an indexer. Indexers are
like default properties in VB.NET, but in C# they must be default, there
is no such thing as a secondary indexer with a special name - every
indexer on a class must be named 'this' and invoked on the client side
like you would call a default property with arguments in VB.NET.
This may force you to refactor some of your code as you convert it to
C#. Also, whereas in VB.NET you can leave out the
parenthesis when you call a function / method or constructor with no
arguments, this is not allowed in C#. For each class you're
converting, you'll need to think carefully about what should be a
property vs. indexer vs. method, and then adapt your client side code to
call it that way.
Also, if you define an indexer, the client side
code must invoke the indexer like an array with square brackets 
rather than parenthesis. SharpDevelop is not able at conversion
time to tell the difference between an indexer and a property, and so it
converts them all with parenthesis. After conversion, you'll need
to convert parenthesis to  brackets where needed.
- VB Functions - If you want to get rid of references
to the VB namespace entirely, there are a number of function calls that
will need to be converted to more basic funtions in .NET:
should be changed to expression.ToString(formatString).
can (usually) be changed to month.ToString(abbrev
? "MMM" : "MMMM").
DateAndTime.DateDiff(interval, a, b) can be changed (usually) to
accessing a property on the TimeSpan returned by
(a-b). For differences in units of years, quarters, or
months, you usually need custom code that is tailored to your
can be replaced with s.Split(new string
- Event Handlers - Whereas VB has the Handles
keyword, C# has no such thing - it is instead expected that the
developer will call AddHandler or use the += operator to add event
handlers explicitly to events. Search through the original VB
module to find all the places where Handles was used, and add expilicit
calls to the C# code to make sure these events get handled in the same
way, if the conversion process did not already take care of this for
you. And if this is a web page, make sure that the event handlers
are wired up in the Page_Init call, after InitializeComponent is called,
and not in the constructor function, because the controls don't get
created until after InitializeComponent is called.
- Foreach Loop Variables - The conversion process
will create two separate variables a foreach loop - the iterator, and a
second variable which is assigned from it in the loop body. This
is done because in C# the loop variable cannot be modified by the loop
code, and having two separate variables prevents this from being a
problem. However it is also very wordy and sometimes wrong.
Search for all the instances of foreach in your code, and change the
loop variable to be a single variable declared using 'var' wherever
possible for simplicity.
- Website App_Code - Since a website cannot be
converted as an entire project by SharpDevelop, an alternate strategy is
recommended here. If the website has a lot of code in the App_Code
directory, create a new empty C# class library specifically for the
project and begin moving App_Code modules out of here one at a time into
the new class library. Load the module code into a new file in
SharpDevelop, convert that single file to C#, and paste it into a new
file in the class library. Repeat the above steps for this file to
fixup all the conversion errors. Then comment out the module from
the website, and adjust all calls to the module to go to the class
- Website Pages - these cannot be converted the same
way as App_Code modules because there is a tight coupling between the
ASPX file and the code-behind file. Controls members are defined by name
in the ASPX file, and the compiler recognizes these automatically in the
code-behind file. If you try to move the code-behind file to a
separate class library, this link gets broken and the members are no
longer defined (except where you explicitly define them).
to deal with this is to create a separate class to hold the logic and
have the constructor of this class use the Page to find the controls
that it needs and wire itself up to those controls. This can be a
good way to re-use form code between website or even on multiple similar
forms on the same website. However, it is also a fair amount of
work, and it is not strictly necessary during conversion.
faster alternate approach which can be used for web pages is just to
convert the individual files in place to C#. Unlike app code
modules, website projects are fully able to have a mix of VB and C# code
behind files in web pages, and the debugger can even step into both
kinds of file simultaneously.
To convert the file, load the
content of the code behind file into a new empty VB file in
SharpDevelop, convert it to C#, and manually create a new .aspx.cs file
in the website directory next to the .aspx.vb file, and paste in the
contents. Then through Windows Explorer rename the .vb file to
.vba so that the compiler ignores it. Open the .aspx file in a
text editor and change the top line to show
Language="C#" and the updated path for the
CodeFile attribute. Then go to Website, Unload Project, and
then right click the project and Reload Project to see the changes. Now
proceed to fixup the C# file that has just been converted using the
rules followed previously.
After you've fully migrated a project to C# and tested it, you can begin
cleanup of VB references as follows:
- Increment / Decrement - You can search and replace
+= 1 with ++
and -= 1 with --
- Remove Unused Usings - For each file in your
project, you can trim out unused using directives by right clicking the
source file, Organize Usings, Removed Unused Usings.
- VisualBasic References - Search for the text
VisualBasic throughout the project or solution. Use the above
steps to replace these calls with the equivalent core .NET functions.