As C# and .NET have evolved over the years, I am always amused by how C# has continued to “catch up” to Visual Basic ‘s (VB) capabilities. Being that VB was created in 1991 while C# was released with .NET in 2002, VB was a little bit more mature when C# was released.

For example, it wasn’t until 2005 when C# finally started supporting static classes. VB modules have always done the same thing. However, C# is wordier than VB in this case. For every member defined in a C# static class, they each must be defined with the static keyword. Meanwhile, all members defined in a VB module are automatically consider shared without the necessity for the Shared keyword in their definition.

C#4 and .NET 4.0 in 2010 finally introduced optional parameters. VB has had support for them all along since the early days of VB before .NET was released. Calling some of the Office APIs with C# was just painful in the past.

VB isn’t by any means perfect though. Some things are a bit odd/funny, such as VB still supporting such things as the built-in Financial class with its functions for calculating interest rates. Cool and probably still being used by apps today.

Granted, VB has also had to catch up in some ways as well. For example, VB finally removed the necessity for (  _) space underscores if code continued on another line. As well, it wasn’t until .NET 2.0 when Microsoft released a new VB compiler that would identify if your Catch blocks were out of order. In .NET 1.0/1.1, you could write “dead” VB Catch blocks that would never run while the C# compiler has always caught these errors.

As well, only C# will allow you to play with pointers via the “unsafe” code blocks. I doubt if VB will ever have this capability.

A couple of things that C# developers have always wished they had was the With/End With block and the drop down menus in Visual Studio for creating/handling event handers for WPF, WinForms, and WebForms.

Back to the title of this article – the VB Static variable. In VB, the Static keyword is not the same as “static” in C#. VB uses the “shared” keyword to define a “class-level” variable that is shared amongst all instances (objects) of the class. Otherwise, simply declare your variable inside a module and it is automatically shared.

Instead, the VB Static keyword is used to define a local variable in a method that holds its value between multiple method invocations. As well, I call it “ultra private” because the other class members don’t even have access to this variable! It’s unique to the class instance so if you instantiate the class twice, you will get two VB Static variables (method-level variables that hold state).

C# does not support these types of local variables. I doubt if they ever will add this capability. True OOAD developers will probably tell you these variables should not even exist! All local variables created within a method must immediately die when the method invocation ends. I suspect this was added to VB.NET as a carryover feature from VB 6. It probably needed this feature because it truly object-oriented (no inheritance).

Still – I think it’s cool that it is still there and I wanted to remind the VB-ers out there how this thing worked. It does encapsulate a variable a step further than even a private class-level variable. It’s one extra layer of security that can be easily overlooked.

Here’s a class (TestClass) with a private Integer field that can be access by all class member. Meanwhile, inside of a method is a local VB Static variable that can only be accessed inside the method. Note that no other members of the class can access it yet it maintains state between calls to the method.

Public Class TestClass
  Private ClassLevelCount As Integer = 0

  Public Sub ClassLevelAddOne()
    ClassLevelCount += 1
    Console.WriteLine("ClassLevelCount = {0}", ClassLevelCount)
  End Sub

  Public Sub ClassLevelAddTen()
    ClassLevelCount += 10 ' This method can change it too! 🙂
    Console.WriteLine("ClassLevelCount = {0}", ClassLevelCount)
  End Sub

  Public Sub UltraPrivateAddTen()
    ' ==================================================================
    ' Doesn't work. This method doesn't have access to UltraPrivateCount
    ' I can't change this and had to comment it out. 🙁
    ' ==================================================================
    'UltraPrivateCount += 1 
    'Console.WriteLine("UltraPrivateCount = {0}", UltraPrivateCount)
  End Sub

  Public Sub LocalVarAddOne()
    Dim LocalVarCount As Integer = 0
    LocalVarCount += 1
    Console.WriteLine("LocalVarAddOne = {0}", LocalVarCount)
  End Sub

  Public Sub UltraPrivateAddOne()
    ' Local variable that holds state between method invocations.
    Static UltraPrivateCount As Integer = 0
    UltraPrivateCount += 1
    Console.WriteLine("UltraPrivateCount = {0}", UltraPrivateCount)
  End Sub
End Class

Look how the VB Static variable is defined in the sub call UltraPrivateAddOne(). Even though we are assigning 0 to it the first time the method is called, that piece of initialization code will be ignored when the method is called again because it is declared as Static.

Now we need a Main() method that calls these methods so we can analyze the results. Here we go:

Module Module1
  Sub Main()
    Console.WriteLine("tc1")
    Dim tc1 As New TestClass()
    Dim tc2 As New TestClass()

    tc1.ClassLevelAddOne()
    tc1.ClassLevelAddOne()

    tc1.ClassLevelAddTen()
    tc1.ClassLevelAddTen()

    tc1.LocalVarAddOne()
    tc1.LocalVarAddOne()

    tc1.UltraPrivateAddOne()
    tc1.UltraPrivateAddOne()

    Console.WriteLine()

    Console.WriteLine("tc2")
    tc2.UltraPrivateAddOne()
    tc2.UltraPrivateAddOne()
  End Sub
End Module

Note that we are trying to add one and ten to a class-level variable. Then we try adding one to a local variable. We can do all this in C# as well. However, we try adding one to the Static variable (only in VB!), and it continues to increment in value inside the method.

For fun, we also create another object (tc2) and see if it has the same VB Static variable, which it does not.

Here are the results:

VB Static variable

Need a super private variable just for one method? Consider declaring it as Static: the VB Static variable. Happy coding!