What C# Devs Should Know About VB Programming
VB and C# share many similarities, but also have a handful of significant differences; learn what you need to know to program effectively in VB as a C# programmer.
Technologies mentioned in this article include C#, and VB.NET.
I have a great job opportunity that leverages a lot of my existing skills. While I used to use Visual Basic 5 and 6 a long time ago, all my .NET code has been written in C# and this job requires that I work in Visual Basic .NET. The team I'm joining is confident they can help me come up to speed, but do you think I can make the transition, and what do you think I should know as I start coding in VB?
It's great that your new team is ready to support your immersion into Visual Basic. It's always a bad idea to exaggerate skills, but since everyone is being honest, I think you'll be successful in the transition. Many people have become quite comfortable and even fallen in love with the "other" language -- whether it's C# coders learning VB or VB coders learning C#.
The second part of your question is worth discussion. I've been a crossover coder for years and have come to appreciate the subtle differences between the languages. I assume you've seen VB and understand the obvious differences such as line continuation characters and synonyms such as Shared/static, as well as obvious operator differences such as single equal for comparisons and <> for not equal to. You can review synonyms in the help under keywords in the index.
Coders can become annoyed if they don't make peace with the unique attitude of each compiler. For example, the VB compiler offers immediate support because of the background compiler and auto-complete. One thing that will help you tremendously is to learn to let the editor work for you, particularly in casing all symbol names outside their definitions. While it sometimes happens a bit later during compile, VB corrects these for you, leaving fully consistent casing, and it does this without you having to do any work. Similarly, VB will finish block constructs and few VB coders I know actually type "Then" at the end of an If statement or worry about the space in the middle of EndIf. VB lets you ignore parentheses in many scenarios. Start out never typing them and let the compiler tell you where they are needed.
I hope you'll be working in Visual Studio 2008 because the location-aware IntelliSense narrows the IntelliSense options to those valid in the current context. In some cases, you'll choose between typing a symbol or selecting a keyword, so become comfortable using the down arrow to select the keyword. IntelliSense has two tabs: Common and All. You'll need to decide what works best for you; I always use the All tab. If you're accustomed to using Enter to select an IntelliSense entry, you'll have to modify that keystroke to use another whitespace, punctuation character, or Ctl-Enter.
You don't need to adopt the VB keyboard shortcuts. Visual Studio allows you to code in VB with C# shortcuts and in C# with VB shortcuts. This will be local to your machine, so your shortcuts won't collide with those of other coders on your team unless you're sharing computers.
Sometimes the VB editor becomes a bit too helpful, and you want to escape what it's currently doing. The escape key will close out the auto-complete and IntelliSense dialogs. I wish it were more helpful in quietly removing semicolons when you accidentally type them. Ask for that on Connect if you find it as annoying as I do.
VB is flexible about whether variables must be declared (Option Explicit), whether variables are strongly typed (Option Strict), how comparisons are done (Option Binary), and whether type inference is used (Option Infer). Unless your team is already using it, don't use Option Binary. This is a backwards-compatibility feature, and it's best to state how comparisons are done at the location of each comparison. A common best practice is to turn on both Option Strict and Option Explicit. If you need late binding, you can turn Option Strict off in a single file. Note that this is file-based, not class-based, and different parts of the same class can have different Option settings if you use partial classes.
The Imports statement supports both partial namespaces and aliased namespaces. You can use aliased namespaces to provide context to classes within your application and to resolve ambiguities while retaining code clarity in either VB or C#. VB's partial namespace support lets you include part of the namespace in the Imports statement and part inline:
Private x As ObjectModel.Collection(Of String)
VB provides project-level shortcuts for imports, options, and namespaces. If you include an Option in the project dialog, it will apply to all files that don't offer a contradictory setting. Imports at the project level are used throughout the project and can't be removed for individual classes. The default VB project includes a number of imported namespaces that you might wish to remove, particularly System.Collections (use System.Collections.Generic instead). Files can, of course, add additional Imports. You can alias a project-level import by typing the alias as a new user imports (see Figure 1). To remove a project-level alias, merely uncheck it and Visual Studio will remove it later.
If you provide a namespace at both the project and file level, the file namespace is concatenated to the project namespace. If this does not accommodate your namespace pattern, you'll have to alter the project namespace and change or add file-level namespaces.
Snippets are as valuable in VB as C#, but they don't show up in IntelliSense. There are more than 400 snippets available in VB: It's easiest to explore them through the menus. Once you find snippets that you use often, memorize the start of their abbreviations and access them with <partial abbreviation> ? tab, selecting the correct snippet as needed. You can also use ?? to get a full list of snippets.
There are several VB assemblies. Microsoft.VisualBasic is included automatically if you're compiling against most versions of the CLR. This assembly contains the conversion functions and other VB-specific features. The Microsoft.VisualBasic.Compatibility libraries support features of earlier versions of VB that don't have direct equivalents in .NET. Don't use the compatibility libraries in new code.
A few legacy VB features are present even without the compatibility library and should be avoided. The most important thing to avoid is the On Error statement. On Error forces the compiler to emit convoluted IL
and requires significant additional runtime resources to manage this style of exception management. Use the skills you learned in C#: try, catch, finally, and using are all available in VB, and the editor will even fix the capitalization for you. Another feature to consider avoiding is the Visual Basic Collection. This collection class creates confusion with the main framework collection, is not strongly typed, and tends to be slow.
Visual Basic has a number of operators, including CType, TryCast, and special cast operators that look like functions. You can tell the difference because the operators are colored blue in the editor and the operators are available whether or not you import the Microsoft.VisualBasic namespace. Both Visual Basic methods and operators are contained in the VisualBasic.dll. Many of the methods and operators are redirected to their counterparts in .NET Framework. Some, such as IsDate, don't have a direct parallel in .NET Framework, while others have subtly different behavior, particularly regarding the localization of dates. VB is location-aware by default. Your team will want to be consistent in whether you use the VB features or use their framework equivalents.
A VB module is the rough equivalent of a C# static class. Within a module, you don't need (and can't use) the Shared keyword. Modules are also the only place where you can define extension methods. A notable difference between VB and C# is that in VB module members can be accessed using only their name: The module name is optional when calling the member. I include it for clarity.
VB uses a declarative syntax for attaching events. The Handles clause appears on the code that will handle the event. When appropriate, multiple methods can handle the same event, and multiple events can be handled by the same method. Use of the Handles clause relies on the WithEvents modifier appearing on the declaration of the underlying variable such as a button. You can also attach property handlers using the AddHandler keyword, and remove them with RemoveHandler. You can customize the grimy details within events, although this is rarely needed.
There are some annoying inconsistencies between VB and C# in recent features. VB propagates nulls in nullable comparisons the same way TSQL does, while C# returns a non-nullable Boolean type and considers a comparison of something else with null false. Immutability of anonymous types is also different with VB's Key keyword. Bill Wagner covers this in more detail in his column this issue, "What VB Devs Should Know About C#."
VB uses different syntax than C# for arrays, although the arrays are identical under the hood. Indexes and size are delimited with parentheses, meaning the same delimiters are used for method parameters and indexes, which can take some getting used to. VB can declare the size of an array in line in the declaration. VB also requires the upper bound, rather than the length of the array. This makes more sense when you realize the upper bound is a shortcut for saying:
Dim myArray3(0 To 3) As Int32
This array contains four elements. The expanded syntax including 0 To is rarely used, but does clarify the intent of the upper bound. You can include the parentheses indicating that a variable is an array on the type or the variable name, but you can declare the upper bound only on the variable name. It's easy for C# coders using VB.NET to create arrays that are one element larger than intended. When you loop through an array using the index, you'll need to stop one shy of the count because VB's For statement includes the top bound.
For i = 0 To myArray.Length - 1
You can evaluate indexes in different ways using the Step modifier on the For statement. By default, Step is one. If you set it to a higher value, you'll skip indexes. If you set the Step value to a negative number, you'll move backwards through the collection, assuming you also reverse the start and end values.
VB's logical operators look a little funny if you aren't familiar with the history. Prior to .NET, Booleans were numeric integers with False equal to zero and True equal to -1 because -1 has all bits set and is the opposite of False. The And operator performed a bitwise And returning True if the result was not equal to zero. In .NET, And retains bitwise semantics of shortcutting and can be used with either integers or Booleans. AndAlso is the short-circuited Boolean-only operator. Similarly, Or has bitwise semantics while OrElse has short-circuited Boolean semantics. This history also explains why the VB conversion operators CInt, CLng, and CShort return -1. Other than what's returned by this conversion operator, the value of False is the same in VB and in the framework.
VB has a With keyword that simplifies setting a variable for use within a block and lets you access this temporary variable with a naked period. If your team uses With, you'll have to be comfortable using it:
With New Data.SqlClient.SqlConnection(conn)
The With construct is especially useful when you are using properties in a different namespace. When you're working with a convoluted name with many dots, you'll get a slight performance advantage using With because the full name is only resolved once. While this looks a bit like a using block, it doesn't dispose of the variable and can be used with either a new or existing variable. VB also has a Using block.
One of the most significant features of VB is the My system. This provides a "speed dial" into many important features of the framework. You can also extend the My system for your own needs. Another large-scale productivity feature is the Windows application framework. This provides simple startup behavior and application-wide event management for WinForm applications.
I think you'll be successful in your transition because the large and complex features are all in the libraries. As you switch into VB, you'll encounter many small issues that reflect the slight difference in focus between VB and C# and their respective legacies. VB aims at clarity, limiting typing, language discoverability, and overall productivity. The most significant thing missing in VB is iterators. Bill Wagner and I paired our columns this month because the question is meaningful in both directions -- for coders moving into either language. You'll find a number of other subtleties in back issues of our columns, as well as Bill McCarthy's On VB column.
Kathleen is a consultant, author, trainer and speaker. She’s been a Microsoft MVP for 10 years and is an active member of the INETA Speaker’s Bureau where she receives high marks for her talks. She wrote "Code Generation in Microsoft .NET" (Apress) and often speaks at industry conferences and local user groups around the U.S. Kathleen is the founder and principal of GenDotNet and continues to research code generation and metadata as well as leveraging new technologies springing forth in .NET 3.5. Her passion is helping programmers be smarter in how they develop and consume the range of new technologies, but at the end of the day, she’s a coder writing applications just like you. Reach her at email@example.com.