12.3. Anonymous Types

Often when you are manipulating data you may find that you need to record pairs of data. For example, when iterating through people in a database you might want to extract height and weight. You can either use a built-in type (in this case a Point or PointF might suffice) or create your own class or structure in which to store the information. If you do this only once within your entire application, it seems quite superfluous to have to create a separate file, think of an appropriate class or structure name, and define all the fields, properties, and constructors. Anonymous types give you an easy way to create these types using implicit typing, which you have just learned about.

VB.NET

Dim personAge = New With {.Name = "Bob", .Age = 55}

C#

var personAge=new {Name="Bob", Age=55};

In the preceding example, you can see that the personAge variable is being assigned a value that is made up of a String and an Integer. If you were to interrogate the type information of the personAge variable, you would see that it is named "VB$AnonymousType_0'2[System.String,System.Int32]" (or "<>f__AnonymousType0'2[System.String,System.Int32]" in C#) and that it has the properties Name and Age. One of the points of difference between C# and VB.NET is whether these properties are read-only (i.e., immutable) or not. In C# all properties of an anonymous type are immutable, as shown by the IntelliSense in Figure 12-3. This makes generating hash codes simpler. Essentially, if the properties don't change then they can all be used to generate the hash code for the object, which is used for accessing items within a dictionary.

Figure 12.3. Figure 12-3

While the properties of the variable personAge are immutable, it is possible to assign a new object to personAge. The new object must have the anonymous type structure, which is determined by the names, types to, and order of the members.

In contrast, the properties in VB.NET by default are not read-only, but you can use the Key keyword to specify which properties should be immutable and thus used as part of the hash code. Figure 12-4 shows how you can make the Name property read-only by inserting the Key keyword before the property name. Again, this is indicated with appropriate IntelliSense when you attempt to assign a value to the Name property. The Age property, however, is still mutable.

Figure 12.4. Figure 12-4

It might appear that having only a single keyed property would give you the most flexibility. However, you should be aware that this might result in objects that are not equal and having same hash code. This happens when two objects have the same values for the keyed properties (in which case the hash code is identical) but different non-keyed properties.

Now that you have seen how you can create an anonymous type using the full syntax, it's time to look at how you can use the condensed form that doesn't require you to name all the properties. In the following example, the Person object, p, is projected into a new variable, nameAge. The first property uses the syntax you have already seen in order to rename the property from FirstName to just Name. There is no need to rename the Age property, so the syntax has been condensed appropriately. Note that when you're doing this, the anonymous type property can only be inferred from a single property with no arguments or expressions. In other words, you can't supply p.Age + 5 and expect the compiler to infer Age.

VB.NET

Dim p As New Person With {.FirstName = "Bob", .LastName = "Jane", .Age = 55}
Dim nameAge = New With {.Name = p.FirstName, p.Age}

C#

Person p = new Person { FirstName = "Bob", LastName = "Jane", Age=55 };
var nameAge = new { Name = p.FirstName, p.Age };

Again, you might wonder where anonymous types would be useful. Imagine that you want to iterate through a collection of Person objects and retrieve just the first name and age as a duple of data. Instead of having to declare a class or structure, you can create an anonymous type to hold the information. The newly created collection might then be passed on to other operations in which only the first name and age of each person is required.

Dim ages = CreateList(New With {.Name = "", .Age = 0})
For Each p In people
    ages.Add(New With {.Name = p.FirstName, .Age = p.Age})
Next

This snippet highlights one of the key problems with anonymous types, which is that you don't have direct access to the type information. This is a problem when you want to combine anonymous types with generics. In the case above, the variable ages is actually a List(of T), but in order to create the list we have to use a little magic to coerce the compiler into working out what type T should be. The CreateList method, shown in the following snippet, is a generic method that takes a single argument of type T and returns a new List(of T). As the compiler can infer T from the example object passed into the method, you don't have to explicitly specify T when calling the method.

Public Function CreateList(Of T)(ByVal example As T) As List(Of T)
    Return New List(Of T)
End Function

While this might seem a bit of a hack, you will see later on that you will seldom have to explicitly create lists of anonymous types, as there is a simpler way to project information from one collection into another.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.136.226