1. Computing

Objects, Parameterized Constructors, Anonymous Types and the With Keyword

Putting it all together in one Quick Tip!

By

As you're reading code in some example, you might see Visual Basic syntax like this:


Dim theVar = New With
   {Key .theFirstProperty = "The First Property",
    .theSecondProperty = 12345}

There are a number of sophisticated ideas here, many of them introduced with VB.NET 2008 (.NET 3.5) to support LINQ, so you usually see them as part of an article that is about LINQ. But they can be used in any context and they're worth understanding on their own.

The thing that you might notice first in this syntax is the use of a With object initializer list to assign values to a New object. The With form allows you to initialize the object without having a "parameterized constructor". So you might be interested in making sure you know how that works. But then you notice that there is no object in the statement. In other words, theVar is a new ... "what"? It has no type specified. There are two properties of different types (String and Integer) in the object but since there's no type name, it's called an anonymous type. And what does "Key" mean? What does it mean when one argument has a Key keyword and the other one doesn't?

That's what this Quick Tip is about.

Let's start at the beginning. When you create a new type, you normally do it with a Class. Let's create theClass as an example:

Public Class theClass
    Public Property theFirstProperty As String
    Public Property theSecondProperty As Integer
End Class

You can declare an object based on theClass with a lot of minor variations in syntax. Here's one way to do it:


Dim theVar As New theClass

This creates an instance, that is, a copy of theClass, named theVar that is of type theClass. The property theFirstProperty is initialized with Nothing and theSecondProperty is 0. These properties were initialized using a special subroutine called a constructor named New. But since there's no subroutine in the class, the system created the necessary code for you. If you need something different ... for example, maybe you would like theFirstProperty to be "George" and theSecondProperty to be 98765 as soon as it's instantiated. There are several ways to do that. First, you can code your own New subroutine.


Public Sub New()
   theFirstProperty = "George"
   theSecondProperty = 98765
End Sub

--------
Click Here to display the illustration
--------

You can also override the default initialization with your own object initialization. Perhaps you have seen code where it's done this way:


Dim theVar As New theClass("Sam", 12345)

Unfortunately, this doesn't work with the New() subroutine shown above because it triggers the syntax error, "Too many arguments to public sub New()".

You can correct this problem in several ways too. One is to parameterize the New constructor by recoding it this way in the class:


Public Sub New(
   ByVal FirstProp As String,
   ByVal SecondProp As Integer)

But suppose you don't have access to the class code and you can't change it. You can also use the With keyword to solve the problem without recoding the class.


Dim theVar As New theClass With
   {.theFirstProperty = "Sam",
    .theSecondProperty = 12345}

--------
Click Here to display the illustration
--------

You might wonder why you have to write the code for a complete class just to use a couple of variables. As the class is coded above, it just holds the values of theFirstProperty and theSecondProperty. In fact, you don't. You can just let the VB compiler create the class for you by simply leaving out the class name.


Dim theVar = New With
   {.theFirstProperty = "Sam",
    .theSecondProperty = 12345}

The compiler creates a class about like the one shown above, except that it doesn't have a name. For this reason, it's called an anonymous type. Anonymous types can have methods as well as properties and are used extensively in LINQ. In this LINQ query, theVarQuery returns a value that is an anonymous type.


Dim theVarQuery = From theTable In theDB
   Select theTable.theField1, theTable.theField2

Not having a name does create a few problems, so VB has another new "key" word to help out: Key.

One problem is telling when one anonymous type is the same as another. The way .NET normally decides whether two instances of an object are the same is the use of the Equals method. (Equals is one of the five native methods in the Object object.)


Dim theVar = New With
   {.theFirstProperty = "Sam",
    .theSecondProperty = 12345}
Dim theOtherVar = New With
     {.theFirstProperty = "Sam",
      .theSecondProperty = 32323}
' Displays False - theSecondProperty not equal
Console.WriteLine(theVar.Equals(theOtherVar))

But .NET doesn't always check the whole object when testing for equality. If a Key keyword is specified, then just those elements will be tested.


Dim theVar = New With
   {Key .theFirstProperty = "Sam",
    .theSecondProperty = 12345}
Dim theOtherVar = New With
     {Key .theFirstProperty = "Sam",
      .theSecondProperty = 32323}
' Displays True
Console.WriteLine(theVar.Equals(theOtherVar))

If Key is present in the object definition, another of the five Object methods, GetHashCode, also ignores the others properties.

Interesting fact: Non-Key properties of VB anonymous types are read-write, but all properties of C# anonymous types are read only. In other words, given the code above, you can write this code in VB.NET:


theVar.theSecondProperty = 55555
  1. About.com
  2. Computing
  3. Visual Basic
  4. Quick Tips
  5. The With Keyword, Parameterized Constructors, Anonymous Types and Objects

©2014 About.com. All rights reserved.