Friday, 30 March 2007

There are four (development) life annoyances that I can do without:

  1. Recruiters who only use the state abbreviation to describe a job location. "Urgent need for Senior .NET Developer, Location: CA"
  2. Forum posters who demand code for entire applications. "Please send me chat server code -- urgent."
  3. Repeated requests for Interview Questions.  I've covered this elsewhere.
  4. 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];
           A
nObjectType SomeObject = (AnObjectType)SomeArrayList[SomeIndex];
ala VB:  Dim SomeObject as AnObjectType = SomeHashtable(SomeKey)
          
Dim SomeObject as AnObjectType = SomeArrayList(SomeIndex)
          'or if Option Strict is on
          D
im 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.
.NET | 2.0 | Annoyances
Friday, 30 March 2007 17:12:15 (Eastern Standard Time, UTC-05:00)   #     Comments [2]  | 
Thursday, 29 March 2007

I am not a graphic designer, nor should I be allowed to play one on TV.  For the last three years I have been looking at the site I "designed" and was getting a bit tired of it.  So I hired a very talented graphic artist, Alissa Taylor, to give it a brand new look

Of course, I then tried to blend the new look into a blog skin.  So what you see here is my fault.

 

Thursday, 29 March 2007 22:46:16 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Wednesday, 14 March 2007
Sometimes I see a method and say "Where have you been all my life?"  When it's in code I wrote over a year ago, I have to say "How did I ever let you go?"  I'm writing this so I don't ever forget it again and to introduce the most useful class that holds it.

The method in question is quite simple, but very useful...

Path.GetFileName(SomeFilePath)

It takes a full file path and just returns the File Name and Extension. Very handy when uploading files or checking URLs.  So useful, I wrote my own version of the function and put it in the base web page class of my projects.   So today I am wandering through some code and there it was.  I used it in a method that I wrote almost 2 years ago and then FORGOT about it. Duh, talk about reinventing the wheel. 

And there are more wheels....

Path.GetFileNameWithoutExtension(SomeFilePath)

Nice! Saves an IndexOf or Split call to get the goodies.

Path.ChangeExtension(SomeFilePath, NewExtension)

Quick change file extension and it makes sure there is a dot between them.

Path.GetPathRoot(SomeFilePath)

Gets the other side of the file path.

But the real nice one is this one...

Path.Combine(SomeFilePath1, SomeFilePath2)

This is the one I REALLY wish I knew about.  There are so many things that need to be checked to join two parts of a path together properly.  Is one of the parts blank?  Does part 1 end with a path separator, does part 2 start with one?  This one call replaces 12-15 lines of code. 

Oy, if I had only remembered this class, it could have saved me a few hours of my life. Need to investigate the Framework a little more thoroughly in the future. 

As for the Path class -- she's never leaving my side again. 

Wednesday, 14 March 2007 21:11:17 (Eastern Standard Time, UTC-05:00)   #     Comments [1]  | 

Theme design by Dean Fiala

Pick a theme: