Since it was introduced in VB.NET 2008, LINQ has become fundamental in VB.NET - but it's still widely misunderstood. This article is one of a series at About Visual Basic that covers the major ways to program LINQ. The goal is for a beginning Visual Basic .NET programmer to get up to speed on LINQ. If you found this article from a search and you would like to start at the beginning, you can find an introduction to the overall LINQ technology - what it covers and what you can do with it - in the article LINQ - An Example Driven Introduction with an example showing how LINQ could be used to start web pages using selections made with CheckBox controls. There is an index to all of the articles in the series in the beginning of the article.
Back to the Future - VB6 Variant Redux?
In VB6, we could use a variable without declaring it as ...
myVar1 = "whatever"
myVar2 = 666
The variables were compiled as Variant types, which could hold anything.
A version of this concept has been carried over into .NET as Object types. If Option Explicit is Off, you can write the same code and the variables now become Object types. Again, they can hold anything. But the default changed in .NET (Option Explicit is On by default) and we were strongly encouraged to declare everything. Not only does this help the compiler catch errors so the application doesn't crash at runtime, but the code runs faster because the variables are "early bound" (the type is determined at compile time) instead of "late bound" (the type is determined at run time). With late binding, the compiler has to add code to figure out what a variable is before using it and that slows everything down. VB6 was slower for the same reason.
But you and I can see that myVar1 should be a string and myVar2 is an integer. Why can't the compiler see this? That was fixed in VB.NET 2008. Now it can. Microsoft calls this "local type inference". The rest of the world often calls it "implicit typing".
Instead of creating them both as Object types, VB.NET 2008 will assume that the first is actually a String and the second is an Integer, like it should. But if you code it like this:
Dim myVar1
myVar1 = "whatever"
myVar1 is still compiled as an Object type.
--------
Click Here to display the illustration
--------
This saves you a few keystrokes, but that isn't the reason Microsoft did it. This new behavior was required by another new feature of VB.NET 2008: anonymous types. And this, in turn, was required by the LINQ: Language INtegrated Query.
Using LINQ, you can now code a query directly in VB.NET that looks something like this:
Dim myCustOrder = From myOrder In Orders _
Where myOrder.Name = "About Visual Basic"
myOrder.Name is never declared. Actually, it is, but the compiler does it automatically and you don't have to. To make this work, Microsoft had to add the capability to their compiler to figure out what a type is from the context. Once they did that, several other advantages became possible too.
If you code something like ...
Dim myCustomer = GetCustomer(myCustNumber)
myTextBox.Text = myCustomer.Name
... and there is no Name member in myCustomer, VB.NET 2005 will crash at runtime. But you don't have to wait and take that risk starting with VB.NET 2008. It will catch it as a compiler error.
Traditionally, the value of Option Explicit and Option Strict have also been to detect type errors. (Assigning a string to an Integer type is a very obvious example that is disallowed by Option Strict.) Option Infer doesn't do much to help out there. It does make coding a bit faster and makes Intellisense work in Visual Studio, but I ran into at least one example where code would work just fine in VB.NET 2005 but crash on a runtime error when the only change is to upgrade to VB.NET 2008.
Here's the code -- This runs fine in VB.NET 2005:
Dim myVar = 12345 Debug.WriteLine( _ "After Assignment to Integer: " _ & myVar.GetType.ToString) myVar = "whatever" Debug.WriteLine( _ "After Assignment to String: " _ & myVar.GetType.ToString)
If you add the same exact code to a VB.NET 2008 project, it crashes with an InvalidCastException error. But note my exact words. If you upgrade the code instead, Option Infer is set to Off. The default is On for new projects.
Maybe this is the only way the people who wrote the conversion code could find to keep applications from crashing this way.
In the initial version of VB.NET 2008, in "Tools > Options > Projects and Solutions > VB Defaults", Option Infer was shown to be On for both upgraded and new projects. But the Compile tab of the project's Properties window was correct. I'd call this a bug in the VB.NET 2008 Express development environment at least.
If you don't have Option Infer set correctly, many Microsoft examples and tutorials simply refuse to work. To be specific, code similar to this example can be found in more than one Microsoft tutorial:
Dim x =
From proc In
System.Diagnostics.Process.GetProcesses
Select proc.ProcessName
For Each y In x
Debug.WriteLine(y.ToString)
Next
The error reported by VB.NET is that the variable y is "not declared".
If Option Infer is set to Off, x is a generic object type. LINQ, the code used, requires that x be an IEnumerable type. Changing Option Infer to On fixes the problem. If you upgrade a project from VB.NET 2005 to VB.NET 2008, this can be a problem.

