There are four (development) life annoyances that I can do without:
- Recruiters who only use the state abbreviation to describe a job location. "Urgent need for Senior .NET Developer, Location: CA"
- Forum posters who demand code for entire applications. "Please send me chat server code -- urgent."
- Repeated requests for Interview Questions. I've covered this elsewhere.
- Lazy gits who can't be bothered to learn how to read either C# or VB.NET. "Thanks for the answer, but my project is in VB.NET, I don't understand C#."
At least once a week, I'll answer a question on forum somewhere with a code example and get a "Thank you, but" response. Often accompanied by a request to rewrite the code in their language of choice. With perfectly named variables and smilies in the comments.
This burns my toast. It takes enormous willpower not to simply respond "find another job you lazy git".
A) We're never talking more than 50 lines of code, usually it is around 20.
B) 3/4 of the friggin' code is manipulating
.NET Framework objects using
.NET Framework methods and
.NET Framework properties -- which are -- wait for it...
THE SAME FOR BOTH C# and VB.NET!So this post is a (no longer) quick and dirty guide for figuring out how to translate C# into VB.NET (and vice versa, but frankly 92.6% of the time its a VB coder who complains). It will become my standard response for all the future lazy gits.
Let's start at the top (of the class file that is)...
Need to reference a namespace...
ala C#: using System.Data.SqlClient;
ala VB: Imports System.Data.SqlClient
Note the ubiquitous semicolon (
;). C# statements can span pages like a sentence in
Ulysses. They don't end until the ; appears. VB statements get one line to do their business, unless they are ended with the awkward _ line continuation (underscore) which allows them to continue one more line unless they are ended with the awkward _, repeat.
A class...
ala C#: public class TheClassINeverHad
{
//fields, methods and properties -- oh my!
}
ala VB: Public Class TheClassINeverHad
'fields, methods and properties -- oh my!
End Class
Ooooh no, C# does everything in lower case! (and its compiler is very strict about keeping it that way)
VB Capitalizes! (not that its compiler cares)
In C#, all code blocks are marked with with brackets{}.
In VB, code blocks usually go until a line that starts with End followed by the type of code block, which iin this case is Class.
Fancier class declarations...
ala C#: public abstract class TheClassINeverHad
ala VB: Public MustInherit Class TheClassINeverHad
ala C#: public sealed class TheClassINeverHad
ala VB: Public NotInheritable Class TheClassINeverHad
Why VB.NET couldn't use the more common OOP vernacular is beyond me.
Interface declarations...
ala C#: public interface IPractical
ala VB: Public Interface IPractical
Hooray, that should be clear even to the laziest git.
Extending a class...
ala C#: public class TheClassINeverHad: APracticalClass
ala VB: Public Class TheClassINeverHad
Inherits APracticalClass
The humble colon does a lot here in C#. The VB syntax leaves nothing to doubt.
Implementing an interface...
ala C#: public class TheClassINeverHad: IPractical
ala VB: Public Class TheClassINeverHad
Implements IPractical
or interfaces...
ala C#: public class TheClassINeverHad: IPractical, IRidiculous
ala VB: Public Class TheClassINeverHad
Implements IPractical
Implements IRidiculous
The colon does everything!
Extending and implementing...
ala C#: public class TheClassINeverHad: APracticalClass, IPractical, IRidiculous
ala VB: Public Class TheClassINeverHad
Inherits APracticalClass
Implements IPractical
Implements IRidiculous
A comment...
ala C#: //This is a 1 line comment
/* This starts a multiline comment
This ends a multiline comment */
ala VB: 'This is a one line comment
There is no such thing as a multline comment in VB, but who comments code anyway?
You really should though.
a field...
ala C#: private int SomeNumberIWillUse;
ala VB: Private SomeNumberIWillUse as Integer
VB.NET surrounds the name of the variable with its access modifier and type. C# gets all that out of the way then tells you the name.
a constant...
ala C#: private const string LAZY_GIT = "Lazy Git";
ala VB: Private Const LAZY_GIT as String = "Lazy Git"
a constructor...
ala C#: public TheClassINeverHad()
{
//Do Something Useful
}
ala VB: public Sub New()
'Do Something Useful
End Sub
C# uses the name of the class to indicate the constructor. The Sub New in VB is a little clearer at first blush.
A structure can be a handy little doo-dad when a class is overkill...
ala C#: public struct Soda
{
public string Name;
public int Calories;
}
ala VB: Public Structure Soda
Public Name as String
Public Calories as Integer
End Structure
More brackets in C#, another End statement in VB. C# shows it inclination for abbreviation. Patterns develop.
Let's not forget enumerations...
ala C#: public enum PlanetValues
{
Mercury = 0,
Venus = 1,
Earth = 2,
Mars = 3,
Jupiter = 4,
Saturn = 5,
Uranus = 6,
Neptune = 7,
Pluto = 8
}
public enum PlanetValues
{
Mercury,
Venus,
Earth,
Mars,
Jupiter,
Saturn,
Uranus,
Neptune,
Pluto
}
ala VB: Public Enum PlanetValues
Mercury = 0
Venus = 1
Earth = 2
Mars = 3
Jupiter = 4
Saturn = 5
Uranus = 6
Neptune = 7
Pluto = 8
End Enum
Public Enum PlanetValues
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Pluto
End Enum
All these enumerations are identical. If no value for the first element is specified it is set = 0, every other unspecified element is incremented one from the previous element. Curiously the C# syntax uses commas and not semi-colons.
a local variable...
ala C#: string DeveloperPersona;
ala VB: Dim DeveloperPersona as String
arrays...
ala C#: string[] CoolDevTools;
string[] CoolDevTools = new string[5];
//assignment
CoolDevTools[0] = SomeString;
ala VB: Dim CoolDevTools as String()
Dim CoolDevTools(5) as String
'assignment
CoolDevTools(0) = SomeString
C# uses square brackets [] for the elements.
VB uses parentheses ().
Ditto for collection elements...
ala C#: AnObjectType SomeObject = (AnObjectType)SomeHashtable[SomeKey];
AnObjectType SomeObject = (AnObjectType)SomeArrayList[SomeIndex];
ala VB: Dim SomeObject as AnObjectType = SomeHashtable(SomeKey)
Dim SomeObject as AnObjectType = SomeArrayList(SomeIndex)
'or if Option Strict is on
Dim SomeObject as AnObjectType = CType(SomeHashtable(SomeKey), AnObjectType)
Dim SomeObject as AnObjectType = CType(SomeArrayList(SomeIndex), AnObjectType)
C# doesn't do narrowing implicit type casts, so an element retrieved from an untyped collection must be explicitly cast. This is done by wrapping the object type in parentheses and smooshing it against the collection name.
VB will implicitly cast unless
Option Strict is On, in which case the CType method must be used to cast the element returned to the proper type.
a method that does NOT return a value...
ala C#: public void ThePerfectMethod(string DeveloperName)
{
// coding goodness
}
ala VB: Public Sub ThePerfectMethod(DeveloperName as String)
'Coding Goodness
End Sub
a method that does return a value...
ala C#: public int ThePerfectMethod(string DeveloperName)
{
// coding goodness
return 42;
}
ala VB: Public Function ThePerfectMethod(DeveloperName as String) as Integer
'Coding Goodness
Return 42
End Function
As with fields and constants, C# states the access modifier and the type being returned by the method before getting to the name. When nothing is returned the type is
void.
VB has separate keywords to differentiate between methods that return nada (Sub) and those that return something (Function).
Parameters are types just like variables are in each language: type Name in C#, Name as Type in VB.
a read/write property...
ala C#: public int TheAnswer
{
get{ return mTheAnswer;}
set{ mTheAnswer = value;}
}
ala VB: Public Property TheAnswer() as Integer
Get
Return mTheAnswer
End Get
Set (Value as Integer)
mTheAnswer = Value
End Set
End Property
a read-only property...
ala C#: public int TheAnswer
{
get{ return mTheAnswer;}
}
ala VB: Public ReadOnly Property TheAnswer() as Integer
Get
Return mTheAnswer
End Get
End Property
a write-only property...
ala C#: public int TheAnswer
{
set{ mTheAnswer = value;}
}
ala VB: Public WriteOnly Property TheAnswer() as Integer
Set (Value as Integer)
mTheAnswer = Value
End Set
End Property
VB.NET needs to be explicity told a property is read- or write-only, C# is happy as long as there is a get or set -- it figures it out.
static(Shared) members...
ala C#: private static int mANumberEveryoneNeeds;
public static ANumberEveryoneNeeds
{
get{return mANumberEveryoneNeeds;}
}
public static void ResetTheNumber()
{
mANumberEveryoneNeeds = 0;
}
ala VB: Private Shared mANumberEveryonNeeds as Integer
Public Readonly Shared Property ANumberEveryoneNeeds() as Integer
Get
Return mANumberEveryoneNeeds
End Get
End Property
Public Shared Sub ResetTheNumber ()
mANumberEveryoneNeeds = 0
End Sub
Shared = static. static = Shared. Static members are shared by ALL instances of a class. The meaning of static is not as immediately a clear as Shared. But it's not that hard to remember.
Branching...
ala C#: if(SomeVariable == 42)
{
Answer = "That's it!";
HasWisdom = true;
}
else
{
Answer = "That's not it.";
HasWisdon = false;
}
//one line syntax
if(SomeVariable == 42)
Answer = "That's it!";
else
Answer = "That's not it.";
ala VB: If SomeVariable = 42 Then
Answer = "That's it!"
HasWisdom = True
Else
Answer = "That's not it."
HasWisdom = False
End if
There's no Then in C#, the boolean expression is wrapped in parentheses and the code to execute is within {}. The brackets are not required if the condition only executes one line. Like most other constructs in VB, the code block ends with a uniquely named End statement: End If.
Note in C# the == is an evaluation operator, as opposed to the assignment operator =. In VB = performs both tasks.
What fun is an If statement without boolean logic...
ala C#: if(!Page.IsPostBack) //Not operator
if(Night != Day) //Inequality
if(Night == Day & Pigs.CurrentState == PigState.Flying) // And
if(Night == Day && Pigs.CurrentState == PigState.Flying) //Conditional And
if(Night == Day | Pigs.CurrentState == PigState.Flying) // Or
if(Night == Day || Pigs.CurrentState == PigState.Flying) // Conditional Or
if(Night == Day ^ Pigs.CurrentState == PigState.Flying) // Xor
ala VB: If Not Page.IsPostBack Then
If Night <> Day Then 'Inequality
If Night = Day And Pigs.CurrentState = PigState.Flying Then
If Night = Day AndAlso Pigs.CurrentState = PigState.Flying Then 'Conditional And
If Night = Day Or Pigs.CurrentState = PigState.Flying Then
If Night = Day OrElse Pigs.CurrentState = PigState.Flying Then 'Conditional Or
If Night = Day Xor Pigs.CurrentState = PigState.Flying Then
VB spells everything out, though <> is a unique feature of the language. The conditional operators AndAlso (&&) and OrElse(||) are tres useful, they short circuit the code and stop evaluting as soon as the appropriate condition is met.
And when If Then is isn't enough...
ala C#: switch(SelectedPlanet)
{
case PlanetValues.Earth:
message = "Live there";
break;
case PlanetValues.Venus:
case PlanetValues.Mars:
message = "Landed there";
break;
case PlanetValues.Mercury:
case PlanetValues.Jupiter:
case PlanetValues.Saturn:
case PlanetValues.Uranus:
case PlanetValues.Neptune:
message = "Flew by";
break;
case PlanetValues.Pluto:
message = "Is it a planet?"
break;
default:
message = "Never heard of it";
break;
}
ala VB: Select Case SelectedPlanet
Case PlanetValues.Earth
message = "Live there"
Case PlanetValues.Venus, PlanetValues.Mars
message = "Landed there"
Case PlanetValues.Mercury, PlanetValues.Jupiter, PlanetValues.Saturn, PlanetValues.Uranus, PlanetValues.Neptune
message = "Flew by"
Case PlanetValues.Pluto
message = "Is it a planet?"
Case Else
message = "Never heard of it"
End Select
In C#, there's only one value per case, but once a supplied value matches a case, the code will "fall through" until it finds a case that executes code. All cases that have code must end with a break;.
In VB, multiple values can be present on a line, it's also possible to do
ranges. The code cannot fall through in VB, but the extra flexibility for defining case values makes it unecessary.
For Loops...
ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index ++)
{
Total += SomeIntegerArray[Index];
CallSomeOtherFunction(SomeIntegerArray[Index]);
}
//A single line For Loop can be done without the brackets
for(int Index = 0; Index < SomeIntegerArray.Length; Index ++)
Total += SomeIntegerArray[Index];
ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1
Total += SomeIntegerArray(Index)
CallSomeOtherFunction(SomeIntegerArray(Index))
Next
In C#, {} brackets define what code gets looped, but a single line statement does not require brackets. Iteration step size is always specified
VB always requires the Next statement. The iteration step size defaults to 1 for VB, to change the iteration step size...
ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index += 2)
{
Total += SomeIntegerArray[Index];
CallSomeOtherFunction(SomeIntegerArray[Index]);
}
ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1 Step 2
Total += SomeIntegerArray(Index)
CallSomeOtherFunction(SomeIntegerArray(Index))
Next
To break out of the loop before it completes...
ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index += 2)
{
Total += SomeIntegerArray[Index];
if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
break;
}
ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1 Step 2
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit For
End if
Next
break is used to get out of every kind of loop in C#. The command for exiting a loop in VB.NET depends on the type of the loop. This can come in handy for nested loops of different types.
For each loops...
ala C#: foreach(Universe PossibleUniverse in PossibleUniverses)
{
if(PossibleUniverse.HasStrongForce)
{
AddToViableCandidates(PossibleUniverse);
}
}
ala VB: For Each PossibleUniverse as Universe in PossibleUniverses
If PossibleUniverse.HasStrongForce Then
AddToViableCandidates(PossibleUniverse)
End if
Next
Ignore the brackets and the for each loops look a lot alike.
Do While Loops...
ala C#: do
{
Total += SomeIntegerArray[Index];
if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
break;
Index++;
}
while(Index < SomeIntegerArray.Length);
ala VB: Do
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit Do
End if
Index += 1
Loop While Index < SomeIntegerArray.Length
Do While Index < SomeIntegerArray.Length
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit Do
End if
Index += 1
Loop
The do loop in C# always executes at least once. The top version of the VB loop does as well. While the second version evaluates the condition before executing. This is the one of the few code structures in VB that doesn't denote it's end using an End statement (the others being the for and for each loops). If it did it would look something like this...
'This is not legal syntax -- just what a Do loop would look like if VB were maddeningly consistent
Do
Total +=SomeIntegerArray(Index)
End Do While Index < SomeIntegerArray.Length
Which is just goofy.
Do Until Loops...
ala C#: do
{
Total += SomeIntegerArray[Index];
if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
break;
Index++;
}
while(Index < SomeIntegerArray.Length);
ala VB: Do
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit Do
End if
Index += 1
Loop Until Index = SomeIntegerArray.Length
Do Until Index = SomeIntegerArray.Length
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit Do
End if
Index += 1
Loop
Wait a second -- there's no
do until in C#.
Until is just the other side of
while. Instead of executing
while a condition is true, it executes
until it is true. When moving from VB.NET to C# just use the while and flip the condition to its opposite. Again the C# loop and the first VB loop execute at least once.
And the last loop is the plain old while loop...
ala C#: while(Index < SomeIntegerArray.Length)
{
Total += SomeIntegerArray[Index];
if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
break;
Index++;
}
ala VB: While Index < SomeIntegerArray.Length
Total += SomeIntegerArray(Index)
If CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
Exit While
End if
Index += 1
End While
While loops in both languages evaluate the condition before executing. Note the while uses the familiar Exit While to break and the End While to terminate the loop.
Finally, a tricky difference -- hooking up event handlers...
ala C#: SomeButton.Click += new ButtonEventHandler(SomeButton_Click);
ala VB: AddHandler SomeButton.Click, AddressOf SomeButton_Click
'or directly declare it
Sub SomeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SomeButton.Click
VB lets you hook up the Handler on the event declaration or add the handler dynamically. C# only allows the dynamic hook.
I think this post has sufficiently covered 93.7% of commonly encountered code. I'd cover
Generics (
VB usage) but I think anyone working with Generics probably doesn't have any problems reading either language.
Here are some reference links...
And for the truly lazy or people who have to translate more than 20 lines of code, there are converters (though you might get some
interesting results) ...
So learn 'em both -- double your code examples, double your employment opportunities -- double your fun.