CHAPTER 12 LINQ TO OBJECTS
Anonymous Types
The final C# language feature I’d like to quickly review is that of anonymous types, which was explored
in Chapter 11. This feature can be used to quickly model the “shape” of data, by allowing the compiler to
generate a new class definition at compile time, based on a supplied set of name/value pairs. Recall that
this type will be composed using value-based semantics, and each virtual method of System.Object will
be overridden accordingly. To define an anonymous type, declare an implicitly typed variable and
specify the data’s shape using object initialization syntax:
// Make an anonymous type that is composed of another.
var purchaseItem = new {
TimeBought = DateTime.Now,
ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55},
Price = 34.000};
LINQ makes frequent use of anonymous types when you want to project new forms of data on the
fly. For example, assume you have a collection of Person objects, and want to use LINQ to obtain
information on the age and Social Security number of each. Using a LINQ projection, you can allow the
compiler to generate a new anonymous type that contains your information.
Understanding the Role of LINQ
That wraps up our quick review of the C# language features that allow LINQ to work its magic. However,
why have LINQ in the first place? Well, as software developers, it is hard to deny that the vast majority of
our programming time is spent obtaining and manipulating data. When speaking of “data,” it is very
easy to immediately envision information contained within relational databases. However, another
popular location for data is within XML documents (*.config files, locally persisted DataSets, or inmemory data returned from WCF services).
Data can be found in numerous places beyond these two common homes for information. For
instance, say you have an array or generic List type containing 300 integers, and you want to obtain a
subset that meets a given criterion (e.g., only the odd or even members in the container, only prime
numbers, only nonrepeating numbers greater than 50). Or perhaps you are making use of the reflection
APIs and need to obtain only metadata descriptions for each class deriving from a particular parent class
within an array of Types. Indeed, data is everywhere.
Prior to .NET 3.5, interacting with a particular flavor of data required programmers to make use of
very diverse APIs. Consider, for example, Table 12-1, which illustrates several common APIs used to
access various types of data (I’m sure you can think of many other examples).
Table 12-1. Ways to Manipulate Various Types of Data
The Data You Want
How to Obtain It
Relational data
System.Data.dll, System.Data.SqlClient.dll, etc.
XML document data
System.Xml.dll
Metadata tables
The System.Reflection namespace
Collections of objects
System.Array and the
System.Collections/System.Collections.Generic namespaces
443