Free mag vol1 | Page 485

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