Dynamic Identifiers: A Sneak Peek at .NET 3.5 for VB Programmers

We veteran VB programmers think we understand untyped, dynamic identifiers, but this technology really is new. Dynamic identifiers are not just weakly typed variants extended to C#. This technology is a solid, strongly typed, natural extension of .NET, and it’s better than what we have had. You will need to understand it to take full advantage of the forthcoming .NET 3.5.

This article offers a first peek at .NET 3.5 with an exploration of the dynamic identifiers feature. By using the May 2006 LINQ CTP (Community Tech Preview), it shows you how to use dynamic identifiers, and explains why the feature is better than previous implementations of weakly typed identifiers in .NET and how it differs from what variant types and untyped variables offered.

Using Late-Bound Types the Old Way

Some programmers like VB because it enables the use of weakly typed, late-bound variables, which in some ways reduce the programmer’s mental workload at the expense of performance. (This is why some programmers think VB is not a hardcore programming language.) In the past, this meant VB programmers could define a variable without expressing the type and then assign some value to that variable. They could use that variable and, like magic, things just seemed to work (see Listing 1).

Listing 1: Late-Bound, Weakly Typed Variables in .Net 1.1/ (This Code Was Written in VS 2003.)

Module Module1
   Sub Main()
      Dim i = 5
      Console.WriteLine(i)
      Console.ReadLine()

      Dim s = "Paul Kimmel"
      Console.WriteLine(s)
      Console.ReadLine()
   End Sub
End Module

In listing 1, i behaves like an integer and s behaves like a string. In terms of programming labor, this is easier for programmers (a good thing) but it carries a performance cost. Listing 2 shows the MSIL that Listing 1 produces.

Listing 2: The MSIL (Microsoft Intermediate Language) Produced by Listing 1

.method public static void Main() cil managed
{
   .entrypoint
   .custom instance void [mscorlib]System.STAThreadAttribute::
      .ctor() = ( 01 00 00 00 )
   // Code size 52 (0x34)
   .maxstack 1
   .locals init ([0] object i,
                 [1] object s)
   IL_0000:  nop
   IL_0001:  ldc.i4.5
   IL_0002:  box      [mscorlib]System.Int32
   IL_0007:  stloc.0
   IL_0008:  ldloc.0
   IL_0009:  call     object
      [mscorlib]System.Runtime.CompilerServices.
                RuntimeHelpers::GetObjectValue(object)
   IL_000e:  call     void [mscorlib]System.Console::WriteLine(object)
   IL_0013:  nop
   IL_0014:  call     string [mscorlib]System.Console::ReadLine()
   IL_0019:  pop
   IL_001a:  ldstr    "Paul Kimmel"
   IL_001f:  stloc.1
   IL_0020:  ldloc.1
   IL_0021:  call     object
      [mscorlib]System.Runtime.CompilerServices.
                RuntimeHelpers::GetObjectValue(object)
   IL_0026:  call     void [mscorlib]System.Console::WriteLine(object)
   IL_002b:  nop
   IL_002c:  call     string [mscorlib]System.Console::ReadLine()
   IL_0031:  pop
   IL_0032:  nop
   IL_0033:  ret
}    // end of method Module1::Main

As illustrated by this MSIL (shown from the utility ILDASM-Intermediate Language Disassembler), the code in Listing 1 treats i and s as special types that require external calls to mscorlib’s GetObjectValue. The problem is that GetObjectValue is an expensive call, and Listing 1 does not allow you to use Option Strict On, which is recommended. If you turn on Option Strict On, Listing 1 will not even compile.

Using Late-Bound Types (Dynamic Identifiers) the New Way

With .NET 3.5, you can use Option Strict On (as recommended) and write code identical to that in Listing 1. However, the compiler correctly interprets the data types of i and s as an integer and a string, respectively. The result is still a reduced workload on the programmer but the backend load is not passed off to the user as poorer performance (see Listings 3 and 4).

Listing 3: Better Code Written in .NET 3.5 Correctly Uses Strict Types, Late-Bound Dynamic Identifiers, and Correctly Emits Strongly Typed MSIL

Option Explicit On
Option Strict On

Imports System.Query

Module Module1

   Sub Main()

      Dim i = 5
      Console.WriteLine(i)
      Console.ReadLine()

      Dim s = Paul Kimmel"
      Console.WriteLine(s)
      Console.ReadLine()

   End Sub

End Module

Listing 4: The MSIL Emitted for .NET 3.5 Correctly Emits the Strongly Typed Variables i and s as an Integer and a String, Respectively

.method public static void  Main() cil managed
{
   .entrypoint
   .custom instance void
      [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
   // Code size       37 (0x25)
   .maxstack  1
   .locals init ([0] int32 i,
                 [1] string s)
   IL_0000:  nop
   IL_0001:  ldc.i4.5
   IL_0002:  stloc.0
   IL_0003:  ldloc.0
   IL_0004:  call       void [mscorlib]System.Console::WriteLine(int32)
   IL_0009:  nop
   IL_000a:  call       string [mscorlib]System.Console::ReadLine()
   IL_000f:  pop
   IL_0010:  ldstr      "Paul Kimmel"
   IL_0015:  stloc.1
   IL_0016:  ldloc.1
   IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
   IL_001c:  nop
   IL_001d:  call       string [mscorlib]System.Console::ReadLine()
   IL_0022:  pop
   IL_0023:  nop
   IL_0024:  ret
}    // end of method Module1::Main

In .NET 3.5, dynamic identifiers mean that extremely late-bound types still work, but the correct type is resolved and emitted dynamically and correctly.

Programming Ease with Static Typing Benefits

Dynamic identifiers allow the easy programming that VB programmers have come to expect but with all the benefits of static typing. Static typing enable bugs to be identified at compile time and not runtime, and it improves performance by eliminating expensive COM Interop calls and the overhead of variant usage.

More importantly, dynamic identifiers are an essential underpinning of the new LINQ (Language INtegrated Query) technology. LINQ, which will make tedious programming tasks easier and access to data and queries uniformly accessible, depends on dynamic typed identification.

About the Author

Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming and .NET. Check out his new book UML DeMystified from McGraw-Hill/Osborne. Paul is a software architect for Tri-State Hospital Supply Corporation. You may contact him for technology questions at pkimmel@softconcepts.com.

If you are interested in joining or sponsoring a .NET Users Group, check out www.glugnet.org.

Copyright © 2007 by Paul T. Kimmel. All Rights Reserved.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read