CHAPTER 11 ADVANCED C# LANGUAGE FEATURES
// Now show the color and make.
Console.WriteLine("My car is a {0} {1}.", myCar.Color, myCar.Make);
// Now call our helper method to build anonymous type via args.
BuildAnonType("BMW", "Black", 90);
Console.ReadLine();
}
So, at this point, simply understand that anonymous types allow you to quickly model the “shape”
of data with very little overhead. This technique is little more than a way to whip up a new data type on
the fly, which supports barebones encapsulation via properties and acts according to value-based
semantics. To understand that last point, let’s see how the C# compiler builds out anonymous types at
compile time, and specifically, how it overrides the members of System.Object.
The Internal Representation of Anonymous Types
All anonymous types are automatically derived from System.Object and, therefore, support each of the
members provided by this base class. Given this, we could invoke ToString(), GetHashCode(), Equals(),
or GetType() on the implicitly typed myCar object. Assume our Program class defines the following static
helper function:
static void ReflectOverAnonymousType(object obj)
{
Console.WriteLine("obj is an instance of: {0}", obj.GetType().Name);
Console.WriteLine("Base class of {0} is {1}",
obj.GetType().Name,
obj.GetType().BaseType);
Console.WriteLine("obj.ToString() == {0}", obj.ToString());
Console.WriteLine("obj.GetHashCode() == {0}", obj.GetHashCode());
Console.WriteLine();
}
Now assume we invoke this method from Main(), passing in the myCar object as the parameter, like
so:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Anonymous Types *****\n");
// Make an anonymous type representing a car.
var myCar = new {Color = "Bright Pink", Make = "Saab", CurrentSpeed = 55};
// Reflect over what the compiler generated.
ReflectOverAnonymousType(myCar);
...
Console.ReadLine();
}
425