C# Anonymous Types

A new feature of C# 3.0 is the ability to create anonymous types. These interesting classes are defined for temporary use within class members. They allow the convenient encapsulation of read-only properties without the need to code a complete class.
What is an Anonymous Type?
Usually well-defined classes encapsulate the behavior and state of a type of object, hiding the implementation details from the class’ consumers. However, sometimes a lightweight class will be defined that contains only properties and that is for use in only a small section of code. Creating a new definition for such a class can be time-consuming when considered against the benefits obtained.
C# anonymous types allow lightweight classes containing read-only properties to be quickly declared and assigned using a convenient syntax. These types only permit the collecting together of related data items.
They do not permit any additional functionality to be added in the form of methods or other class members.
Creating Anonymous Types
Anonymous types are created using the “var” keyword and a syntax similar to that of implicitly typed variables. Instead of assigning a simple value to the new variable, the object is created using the “new” keyword but with no named type. The “new” keyword is simply followed by a list of properties, each named and assigned a value, within a pair of brace characters {}. The general syntax is as follows:

var varname = new { Prop-Name-1 = prop-value-1, ..., Prop-Name-X = prop-value-X };

To create an anonymously typed object in this manner, each property must be named and a value assigned.
The individual properties are implicitly typed according to the value provided.
To demonstrate this new syntax, try the following sample. This creates a new object based upon an anonymous type that represents a car. The properties of the object are then outputted to the console. NB: If you type the code manually using Visual Studio 2008 you will notice that the class is fully supported by Intelligent.

var dino = new
{
Make = "Ferrari",
Model = "Dino",
Colour = "Red"
};
Console.WriteLine(dino.Make); // Outputs "Ferrari"
Console.WriteLine(dino.Model); // Outputs "Dino"
Console.WriteLine(dino.Colour); // Outputs "Red"

The Object Base Class
Anonymous types are always generated as classes that have a base class of Object. As such, they inherit the members of Object. Four interesting inherited methods are Equals, GetHashCode, GetType and ToString.
Equals Method
Two anonymously typed objects can be compared for a match using either the equality operator (==) or the Equals method. The equality operator is not overloaded so compares the two references, as with comparing objects. If the two references are pointing to the same underlying object data, the result of the operation is true. If the references are different the operation returns false, even if the properties of the two objects match.
The Equals method is overloaded in the anonymous type to provide different functionality to the base class version. When two anonymously typed objects are compared using the method, each property is compared individually. If every property is an exact match, the result is true. This allows anonymous types, which are reference types, to behave similarly to value types.
NB: If the anonymous types have different signatures, the == operator may not be used and the Equals method will return false. The types are considered different if the named properties are not an exact match, even if the same names are used in a different order. This can be seen in the following code sample:

var cat1 = new { Name = "Mog", Age = 5 };
var cat2 = new { Name = "Tabby", Age = 5 };
var cat3 = new { Name = "Tabby", Age = 5 };
var cat4 = new { Age = 5, Name = "Mew" };
bool result;
result = cat1 == cat2; // result = false
result = cat3 == cat4; // Does not compile
result = cat1.Equals(cat2); // result = false
result = cat2.Equals(cat3); // result = true
result = cat3.Equals(cat4); // result = false

GetHashCode Method
The GetHashCode method is overridden by anonymous types to provide compatibility with the Equals method. When the hash code is computed, the value of every property in the object is included in the calculation.

var cat1 = new { Name = "Mog", Age = 5 };
var cat2 = new { Name = "Tabby", Age = 5 };
var cat3 = new { Name = "Tabby", Age = 5 };
Console.WriteLine("cat1 / {0}", cat1.GetHashCode());
Console.WriteLine("cat2 / {0}", cat2.GetHashCode());
Console.WriteLine("cat3 / {0}", cat3.GetHashCode());
/* OUTPUT
cat1 / -1957230611
cat2 / -2011558908
cat3 / -2011558908
*/

GetType Method
The type of an anonymously typed object can be determined using the GetType method. If two or more objects contain the same property names and types in the same order, they are both created as the same type.
This is shown in the following sample:

var cat1 = new { Name = "Mog", Sound = "Meow" };
var cat2 = new { Name = "Tabby", Sound = "Mew" };
new { Sound = "Mew", Name = "Tabby" };
Console.WriteLine("cat1 / {0}", cat1.GetType());
Console.WriteLine("cat2 / {0}", cat2.GetType());
Console.WriteLine("cat3 / {0}", cat3.GetType());
/* OUTPUT
cat1 / <>f__AnonymousType1`2[System.String,System.Int32]
cat2 / <>f__AnonymousType1`2[System.String,System.Int32]
cat3 / <>f__AnonymousType2`2[System.Int32,System.String]
*/

NB: Note the names of the anonymous types generated by the compiler. The names may vary slightly from that shown above.
ToString Method
The final method to be considered in this article is ToString. This method generates a string representation of the anonymously typed object. It combines all of the property names and values in a similar format to as they are declared. Using the feline examples for the last time, we can output several strings:

var cat1 = new { Name = "Mog", Age = 5 };
var cat2 = new { Name = "Tabby", Age = 5 };
var cat3 = new { Age = 5, Name = "Tabby" };
Console.WriteLine("cat1 / {0}", cat1.ToString());
Console.WriteLine("cat2 / {0}", cat2.ToString());
Console.WriteLine("cat3 / {0}", cat3.ToString());
/* OUTPUT
cat1 / { Name = Mog, Age = 5 }
cat2 / { Name = Tabby, Age = 5 }
cat3 / { Age = 5, Name = Tabby }
*/

Limitations
Anonymous types have similar limitations to implicitly typed variables. The key limitations are that anonymous types may only be used locally within class members. They may not be used in method parameters or return values, property declarations or as class-scope fields.
An anonymously typed object may be passed to the parameter of a method but must first be boxed into an object. This removes much of the usefulness of the type, so in these situations it is more appropriate to declare a real class instead.

Tagged , . Bookmark the permalink.

2 Responses to C# Anonymous Types

  1. Winston Leffler says:

    I think that is among the so much significant info for me. And i’m happy studying your article. But wanna observation on few general things, The web site taste is great, the articles is really excellent :D. Excellent task, cheers.

Leave a Reply