As the the announcements from the Professional Developers Conference start to sink in I think its worth taking some time to take a closer look at the details of the products and technologies announced.

Obviously one that has received a lot of attention are the new C# 3.0 and VB 9.0 features and thats what I want to look at now. Here I will focus mostly on C# and point out any significant differences in the VB implementation.

The first cab off the rank is implicitly typed local variables which is really an enabling feature which allows you to define a local variable with out explicity specifying its type – that information is inferenced (is that a word). To understand what I mean lets look at the following local declaration which is valid in C# today:

  1 Customer c = new Customer();
  2 int i = 123;
  3 string s = "Hello World";

If we look at this line there is some obvious redundancy there. The C# 3.0 language specification introduces are new keyword “var” which tells the compiler to automatically determine the type of the local variable from its initial assignment, thus the code can be simplied as follows:

  1 var c = new Customer();
  2 var i = 123;
  3 var s = "Hello World";

Of course, Visual Basic .NET has always had this feature so in C# land we are really playing catch-up here:

  1 Dim c As New Customer()

The rules for implicitly typed local variables are the same as VB.NET’s when Option Strict is turned on – that is to say that the type of the local variable can never be in doubt which means the following code is invalid:

  1 var c;
  2 c = new Customer();

Looking at the contrived example above you may be thinking what is the harm in type inferencing, but its not until you expand the sample out to include some conditional logic that the problem becomes more apparent:

  1 var c;
  2 
  3 if (someCondition)
  4 {
  5       c = "Hello World";
  6 }
  7 else
  8 {
  9       c = 123;
 10 }

In order to support this “c” would need to be an object and C# would need to support late-binding and since the type couldn’t be statically determined things like intellisense would be very difficult to support.

I think that most C# programmers will declare their variables this way when they can and fall back to the old declaration syntax when circumstances requirement. One classic scenario that I can think of is when you have some code like the following:

  1 public class Base
  2 {
  3       public virtual void DoSomething() {}
  4 }
  5 
  6 public class Derived : Base
  7 {
  8       public new void DoSomething() {}
  9 }
 10 
 11 public class Program
 12 {
 13       public static Derived GetObject()
 14       {
 15               return new Derived;
 16       }
 17 
 18       public static void Main()
 19       {
 20               var baseObject = GetObject();
 21               baseObject.DoSomething(); // Calls Derived.DoSomething()
 22        }
 23 }

If you weren’t paying attention to what you were doing you might right the code in the main-line expecting to work with the Base type, however, because the inferenced type is Derived (from the GetObject(…) method)  the implementation of DoSomething that gets called is the one that shadows the base classes’ implementation. You could start doing funky things like explicitly casting to the base class but when you start doing that you may as well use explicitly typed local variables.

Finally – you can use the “var” keyword on “for” and “foreach” loops. In the following case the compiler knows that we are enumerating a set KeyValuePair<int, string> instances. Currently the LINQ technical preview for C# doesn’t support intellisense in this scenario which may limit its immediate usefulness somewhat, but I always have trouble remembering what kind of object an enumerator returns so when intellisense is working this has the potential to be a real timesaver.

  1 Dictionary<int, string> dict = new Dictionary<int, string>();
  2 dict.Add(0, "One");
  3 dict.Add(1, "Two");
  4 dict.Add(2, "Three");
  5 foreach (var entry in dict)
  6 {
  7       Console.WriteLine(
  8               "{0}: {1}",
  9               entry.Key,
 10               entry.Value
 11               );
 12 }
 13 

So that is pretty much a wrap for implicitly typed local variables – next up we will look at some features such as object and collection initializers.