Declaring Anonymous Types in VB

Introduction

Using an anonymous type means that the compiler will code
generate a class for you based on context and named
initializers. This article introduces you to anonymous types
and explores some of the variations of their usage.

I am not lazy by nature; the converse is actually true. I
personally spend hundreds even thousands of hours at my
craft, but when it comes to solving problems time is money.
When I'm learning then I don't mind tickling an idea to
determine all of the myriad of ways in which it can be
solved. In practice I use the cheapest, most direct, and
practical approach that meets this test: reasonableness and
sufficiency.

I write a dozen classes a week. I re-write some classes
over and over throughout the years to discover the optimal
solution. In practice though I borrow my own code, the code
of others, or use code generators and tools to get the job
done. Some 'bosses' may want to feel that we programmers are
working hard, but the smart boss will want you to work
smarter not harder. Working smarter means that you leverage
all of the tools and resources available for optimal
results. In Visual Basic, in some contexts, anonymous types
provide reasonable and sufficient solutions and satisfy the
optimal use of time.

Defining an Anonymous Type

An anonymous type quite simply means that you don't
specify a class ahead of time. All you do when you use an
anonymous type is to specify the named fields and values;
the compiler then writes the class for you. Letting the
compiler write your classes is a great labor saver. Imagine
no syntax errors, no class to debug, and being left with
usable results.

If you interviewed the inventor of anonymous types and
asked why were these invented you might get a variety of
answers. One answer might be anonymous types help when you
are using LINQ. A simple answer plain for all to see is that
for years programmers had to specify every single class by
hand and this is labor intensive. Clearly many classes have
historically been written and may only be used one time.
Suppose for example that you have a customer and contact
information class. Further suppose that you want to display
a customer name and phone number to display this information
in a pick list or report. Some programmers-including me in
the past-have defined a composite class with containing the
desired bits of information. Accumulatively all of these
kinds of classes add up to a significant amount of time over
a project and career. The anonymous type-and technologies
like LINQ-eliminate the need to write these kinds of
classes.

An anonymous type is defined by using the Dim keyword, a
variable name, followed by the assignment operator, the New
With construct, and a list of field names and values. Think
of it as stenography for programmers. Here is a very short
anonymous type definition that defines a simple company
class.

When the compiler encounters the preceding code it
interprets this code as you wanting a class and code. It
then generates one for you. From this point you can use the
object company and modify CustomerID and CompanyName just as
if you had written the class yourself.

Note: CodeRush is a meta-programming tool that writes
code using pre-existing templates and a two or three
shortcut key combination.

Arguably you could use a great tool like CodeRush and the
labor involved in writing the class yourself is less labor
intensive than writing all of the code keystroke by
keystroke, but think of the anonymous types as and an
evolutionary progression from manually writing the code-to
using meta-programming tools CodeRush-to using a shorter
notation. (A neat benefit of CodeRush is of course that you
can iteratively define new CodeRush templates that spit out
user-defined templates. This means now that the anonymous
type exists and you can define a CodeRush template for it.
In this way programmers, learning new idioms and using tools
like CodeRush can stay hyper-productive.)

The anonymous type shown earlier generates a class as if
you had written it yourself. You can verify this with a tool
like Red-Gate's Reflector. Here is the long-hand version of
the customer class, but really who wants to go to all the
trouble for every single class (see Listing 1).

Public Class Customer
Public Sub New()
End Sub
Public Sub New(ByVal CustomerID As String)
FCustomerID = CustomerID
End Sub
Private FCustomerID As String
Public Property CustomerID() As String
Get
Return FCustomerID
End Get
Set(ByVal Value As String)
FCustomerID = Value
End Set
End Property
Private FCompanyName As String
Public Property CompanyName() As String
Get
Return FCompanyName
End Get
Set(ByVal Value As String)
FCompanyName = Value
End Set
End Property
Public Overrides Function ToString() As String
Return String.Format("CustomerID={0}, CompanyName={1}", _
FCustomerID, FCompanyName)
End Function
End Class

Listing 1: The Customer class long-hand.

There are benefits to anonymous types in addition to
saving you time. For instance, every application is
comprised of classes. These classes make up the model that
represents your system. The more classes there are the more
complex your model is. You don't have to model anonymous
types. Generally anonymous types are temporal. Excluding
piddling classes from your system--or the model of your
system--makes it easier for other developers to jump on
board more quickly. And, if you are working on a disciplined
team then of course classes you don't write save you time
managing the model of your system. Saving time writing,
modeling, and learning a system saves a significant amount
of time accumulatively.

Declaring Anonymous Types in VB

Specifying a Key

Anonymous types support defining a key too. Every field
in an anonymous type is readable and writable by default.
You can specify that a field is the key. The key field is
immutable as all such keys should be. The following code
demonstrates how to employ the Key keyword.

In the revised version CustomerID is immutable.
CustomerID will always be the value assigned upon
initialization. If you check Reflector you will see that
this is enforced in the generated code (see Figure 2).

[customerid.jpg]
Figure 2: Note that CustomerID only has a getter and the CustomerID field is private as it should be.

Calling Parameterized Constructors and Using Named Initializers

If you have a pre-defined class, but want to use the
initialize approach for fields that aren't defined in the
constructor then you can combine a parameterized constructor
with named initializers. (I am not using an anonymous type
for this example.) Using the Customer class in Listing 2,
the statement below calls the constructor that accepts a
CustomerID and provides values for other public properties
using the initialize list.

Dim company3 As New Customer("PAULK") With {.CompanyName = "Kimmels
Konfections"}

If you step into the statement then you will see that it
calls the Sub New(ByVal CustomerID As String) constructor
and that the public property CompanyName is initialized too.
Initalizers are supported for anonymous types and user-
defined types.

Using Fields as Initializers

You also have the option for using earlier fields in
initialize lists. For example, if the CompanyName-in our
scenario-is identical to the CustomerID then you can provide
a value for CustomerID and use the CustomerID to initialize
the CompanyName. Here is the syntax for doing so.

In this example, I am using the named type Customer and
setting CompanyName to CustomerID. Using fields in your
initializer list is supported for anonymous types and user-
defined type instantiation as shown above. Let's return to
anonymous types.

Defining Nested Anonymous Types

Just as you can define composite types--classes
containing fields that are other classes--long-hand, you can
define anonymous types with nested types. To do so you use
the initialize approach list and nest the initialization
sequence. The following statement demonstrates this.

In the example notice that I have defined company5 as an
anonymous type with three fields: CustomerID, CompanyName,
and Phone. The difference here is that Phone is an anonymous
type too. Simply repeat the usage of the "New With"
construct for the nested type and provide the initializer
list for the nested type. In this example the compiler will
properly code generate two anonymous classes, one
representing the outer type and the other representing the
nested type. The nested type will be used as the type of the
class property.

Summary

If one is performing a task then lazy is a relative term.
The simple fact of using the easiest, sufficient approach
does not make one lazy. I encourage you to use anonymous
types wherever suitable. Think of anonymous types as a short
hand for class syntax.

Biography

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 upcoming book Professional DevExpress
ASP.NET Controls (from Wiley) now available on
Amazon.com and fine bookstores everywhere. Look for his
upcoming book Teach Yourself the ADO.NET Entity Framework
in 24 Hours (from Sams). You may contact him for
technology questions at pkimmel@softconcepts
.com. Paul Kimmel is a Technical Evangelist for
Developer Express, Inc, and you can ask him about Developer
Express at paulk@devexpress.com
and read his DX blog at http://
community.devexpress.com/blogs/paulk.

Comments

There are no comments yet. Be the first to comment!

You must have javascript enabled in order to post comments.

Leave a Comment

Your email address will not be published. All fields are required.

Name

Email

Title

Comment

Top White Papers and Webcasts

Live Event Date: March 19, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT
The 2015 Enterprise Mobile Application Survey asked 250 mobility professionals what their biggest mobile challenges are, how many employees they are equipping with mobile apps, and their methods for driving value with mobility.
Join Dan Woods, Editor and CTO of CITO Research, and Alan Murray, SVP of Products at Apperian, as they break down the results of this survey and discuss how enterprises are using mobile application management and private …

On-demand Event
Event Date: February 12, 2015
The evolution of systems engineering with the SysML modeling language has resulted in improved requirements specification, better architectural definition, and better hand-off to downstream engineering. Agile methods have proven successful in the software domain, but how can these methods be applied to systems engineering? Check out this webcast and join Bruce Powel Douglass, author of Real-Time Agility, as he discusses how agile methods have had a tremendous …