CHAPTER 11 ADVANCED C# LANGUAGE FEATURES
}
// Show all the details.
Console.WriteLine();
ReflectOverAnonymousType(firstCar);
ReflectOverAnonymousType(secondCar);
Assuming you have called this method from within Main(). Here is the (somewhat surprising)
output:
My car is a Bright Pink Saab.
You have a Black BMW going 90 MPH
ToString() == { Make = BMW, Color = Black, Speed = 90 }
Same anonymous object!
Not the same anonymous object!
We are both the same type!
obj is an instance of: <>f__AnonymousType0`3
Base class of <>f__AnonymousType0`3 is System.Object
obj.ToString() == { Color = Bright Pink, Make = Saab, CurrentSpeed = 55 }
obj.GetHashCode() == -439083487
obj is an instance of: <>f__AnonymousType0`3
Base class of <>f__AnonymousType0`3 is System.Object
obj.ToString() == { Color = Bright Pink, Make = Saab, CurrentSpeed = 55 }
obj.GetHashCode() == -439083487
When you run this test code, you will see that the first conditional test where you call Equals()
returns true and, therefore, the message “Same anonymous object!” prints out to the screen. This is
because the compiler-generated Equals() method makes use of value-based semantics when testing for
equality (e.g., checking the value of each field of the objects being compared).
However, the second conditional test, which makes use of the C# equality operator (==), prints out
“Not the same anonymous object!”, which might seem at first glance to be a bit counterintuitive. This
result is due to the fact that anonymous types do not receive overloaded versions of the C# equality
operators (== and !=). Given this, when you test for equality of anonymous types using the C# equality
operators (rather than the Equals() method), the references, not the values maintained by the objects,
are being tested for equality.
Last but not least, in our final conditional test (where we examine the underlying type name), we
find that the anonymous types are instances of the same compiler-generated class type (in this example,
<>f__AnonymousType0`3), due to the fact that firstCar and secondCar have the same properties (Color,
Make, and CurrentSpeed).
This illustrates an important but subtle point: the compiler will only generate a new class definition
when an anonymous type contains unique names of the anonymous type. Thus, if you declare identical
anonymous types (again, meaning the same names) within the same assembly, the compiler generates
only a single anonymous type definition.
428