Understanding Object Initialization Syntax
•        It is now possible to set property values at the time of object construction using object initialization
syntax.
•        This can be a massive time saver, as we are able to condense multiple lines of code into a single statement.
•        Assume the following Point type, which models an {X, Y} position:
•        Here, we are encapsulating the private data with public properties; however public field data can also be
set with object initialization syntax.
•        The VB Point would have the same functionality in VB-specific syntax.
// C#
public struct Point
{
private int xPos, yPos;

public Point(int x, int y)
{  xPos = x; yPos = y; }

public int X
{
get { return xPos; }
set { xPos = value; }
}
public int Y
{
get { return yPos; }
set { yPos = value; }
}

public override string ToString()
{ return string.Format("[{0}, {1}]", xPos, yPos); }        
}

•        Now consider the following usage of the Point type in C# code.
•        The first two Point allocations work under any version of C#.
•        The final two allocations make use of object initialization syntax.
static void Main(string[] args)
{
// Make a Point by setting each property manually.
Point firstPoint = new Point();
firstPoint.X = 10;
firstPoint.Y = 10;

// Make a Point via custom constructor.
Point anotherPoint = new Point(20, 20);

// Make some Point types using object init syntax.
var yetAnotherPoint = new Point { X = 30, Y = 30 };
Point finalPoint = new Point { X = 30, Y = 30 };
}
•        In VB, object initialization syntax may remind you of the With construct.
•        Rather than authoring a With scope to set each property, we can now do so directly ‘inline’.
•        Notice that each property is prefixed with a dot operator.
' VB
Sub main()
' Object init syntax in VB.
Dim yetAnotherPoint = New Point With {.X = 30, .Y = 30}
Dim finalPoint As Point = New Point With {.X = 30, .Y = 30}
End Sub

•        In the previous code example, yetAnotherPoint and finalPoint were created via the default constructor.
•        When using the default constructor of the type, you are not required to specify a set of parentheses.
•        However, the following code is also permissible.
// C#
var yetAnotherPoint = new Point() { X = 30, Y = 30 };

' VB
Dim yetAnotherPoint = New Point() With {.X = 30, .Y = 30}
•        If you specify a custom constructor, be aware that the properties will be set after the constructor call!
•        Therefore, object initialization syntax could override your initial constructor settings.
•        For example, the following Point will display an X value of 100 and a Y value of 100, despite the supplied
constructor values.
// C#
Point pt = new Point(10, 16) { X = 100, Y = 100 };
Console.WriteLine(pt);

' VB
Dim pt As Point = New Point(10, 16) With {.X = 100, .Y = 100}
Console.WriteLine(pt)

•        Object initialization syntax can be used when properties expose complex types as well.  
•        Consider the following Rectangle type definition which contains two member variables of type Point.
•        Again, VB code would be similar.
public class Rectangle
{
private Point topLeft = new Point();
private Point bottomRight = new Point();

public Point TopLeft
{
get { return topLeft; }
set { topLeft = value; }
}
public Point BottomRight
{
get { return bottomRight; }
set { bottomRight = value; }
}

public override string ToString()
{
return string.Format("[TopLeft: {0}, {1}, BottomRight: {2}, {3}]",
topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
}
}

•        You could now create Rectangle types as so:
// C#
Rectangle myRect = new Rectangle
{
TopLeft = new Point { X = 10, Y = 10 },
BottomRight = new Point { X = 200, Y = 200}
};

' VB
Dim myRect As New Rectangle With { _
.TopLeft = New Point With {.X = 10, .Y = 10}, _
.BottomRight = New Point With {.X = 200, .Y = 200}}
•        This is simply a shorthand notation for the following ‘old school’ approach:
•        As you may agree, object initialization syntax allows us to hydrate an object’s state in a more concise and
functional manner.
// Old school approach (C#).
Rectangle r = new Rectangle();
Point p1 = new Point();
p1.X = 10;
p1.Y = 10;
r.TopLeft = p1;

Point p2 = new Point();
p2.X = 200;
p2.Y = 200;
r.BottomRight = p2;

•        Very closely related to the concept of object initialization syntax, is that of collection initialization.
•        This syntax makes it possible to populate a generic container (such as List<T>) or non-generic types
(such as ArrayList) with items using a syntax which models that of a simple array.
•        Consider the following usage:
•        As you examine the code, ponder the amount of code required under C# 2.0.
// Init a List<T> of Rectangles.
List<Rectangle> myListOfRects = new List<Rectangle>
{
new Rectangle {TopLeft = new Point { X = 10, Y = 10 },
        BottomRight = new Point { X = 200, Y = 200}},
new Rectangle {TopLeft = new Point { X = 2, Y = 2 },
        BottomRight = new Point { X = 100, Y = 100}},
new Rectangle {TopLeft = new Point { X = 5, Y = 5 },
        BottomRight = new Point { X = 90, Y = 75}}
};
•        Unfortunately, the current build of VB does not supply using collection initialization syntax.
•        Previous CTP releases of VB 9.0 did support this feature; however this is no longer the case.
•        Therefore, a VB programmer will need to create the container and then call the Add() method for each
type they wish to insert.
Sub Main()
' Make container first.
Dim myListOfRectangles As New List(Of Rectangle)

' Add items.
myListOfRectangles.Add(New Rectangle With { _
.TopLeft = New Point With {.X = 10, .Y = 10}, _
.BottomRight = New Point With {.X = 200, .Y = 200}})
End Sub
Understanding Anonymous Types                                                        
•        As an object oriented programmer, you know the benefits of defining classes to represent the state and
functionality of a given programming entity.
•        Whenever you need to define a user defined type which is intended to be reused across projects, creating a
new class is common practice
•        Many of these classes provide numerous bits of functionality through a set of methods, events, properties
and custom constructors.
•        Other times, you may wish to define a class simply to model a set of encapsulated (and somehow related)
data points without any associated functionality.
•        Imagine you wish to define the ‘shape’ of data (three strings and 1 integer) but have no need to define
custom members (methods, events, etc).
•        Furthermore, what if this type is only used internally to your current application, and not intended to
reused?
•        If you need such a ‘temporary’ type, would require you to nevertheless build a new class definition by
hand:
class SomeClass
{
// Define a set of private member variables...

// Make a property for each member variable...

// Override ToString() to account for each member variable...

// Override Equals() to account for value based semantics...

// Override GetHashCode()...
}

•        .NET 3.5 now allows you to define an ‘anonymous type’.
•        This can be very helpful when you simply wish to define the ‘shape’ of a type, rather than any custom
functionality.
•        In most programming assignments, this feature will be most useful when interacting with LINQ
technologies.
•        When you define an anonymous type, you do so by making use of implicitly typed local variables in
conjunction with object initialization syntax.
•        Each name / value pair can be accessed after the fact using CLR property syntax.
•        Consider the following anonymous type that models a simple car type.
// C#
static void CreateAndUseAnonymousType()
{
// Make an anonymous type representing a car.
var myCar =
new { Color = "Black", Make = "Saab", CurrentSpeed = 55 };

Console.WriteLine("My car is the color {0}.", myCar.Color);
}

' VB
Sub CreateAndUseAnonymousType()

' Make an anonymous type representing a car.
Dim myCar = New With {.Color = "Black", .Make = "Saab", .CurrentSpeed = 55}

Console.WriteLine("My car is the color {0}.", myCar.Color)
End Sub

•        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.
•        Consider the following helper method which invokes various members of Object for diagnostic purposes.
// C# (VB code would be similar)
static void ReflectOverAnonymousType(object obj)
{
Console.WriteLine("obj is an instance of: {0}",
obj.GetType().Full);
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, consider the following usage and resulting output.
// C# (VB code would be similar)
static void Main(string[] args)
{
// Make an anonymous object representing a car.
var myCar = new {Color = "Black",
          Make = "Saab", CurrentSpeed = 55};

// Reflect over what the compiler generated.
ReflectOverAnonymousType(myCar);
}



•        Here the anonymous type has been assigned the name <Projection>f__0, which is-a System.Object.
•        Do understand that the assigned type name is completely determined by the compiler, and is not
accessible in your code base.
•        Beyond the auto-generated name, each compiler generated type has the following characteristics:
•        A default constructor.
•        The object initialization name/value pairs result in a public property and private read-only backing field.
•        The type is sealed (for security reasons).
•        Each virtual member of System.Object has been overridden.

•        The compiler generated implementation of ToString() simply makes use of StringBuilder to return the
current set of name/value pairs:
•        Again, the names of the properties are a direct result of the anonymous type definition.
// Approximate C# code.
public override string ToString()
{
StringBuilder builder1 = new StringBuilder();
builder1.Append("{");
builder1.Append("Color");
builder1.Append("=");
builder1.Append(this.Color);
builder1.Append(", ");
builder1.Append("Make");
builder1.Append("=");
builder1.Append(this.Make);
builder1.Append(", ");
builder1.Append("CurrentSpeed");
builder1.Append("=");
builder1.Append(this.CurrentSpeed);
builder1.Append("}");
return builder1.ToString();
}
•        The compiler generated implementation of GetHashCode() returns a hash value which is based on the hash
values of each named property:
// Approximate C# code.
public override int GetHashCode()
{
int hashValue = 0;
if (this.Color != null)
{
hashValue ^= this.Color.GetHashCode();
}
if (this.Make != null)
{
hashValue ^= this.Make.GetHashCode();
}
return (hashValue ^ this.CurrentSpeed.GetHashCode());
}

•        The compiler generated implementation of Equals() is a bit more interesting.
•        The Equals() method is implemented to make use of value based semantics.  Therefore, if you have two
anonymous types that have identical name/value pairs, Equals() returns true.
•        However, the compiler does not overload the equality operators for an anonymous type.
•        Recall by default, the equality operators are making use of reference based semantics.
•        Thus, if you use these operators to test for equality of two anonymous types, the return value is false.

•        Consider the following code and resulting output.
•        Notice that firstCar and secondCar have identical name / value pairs.
•        VB code would be similar, using the VB equality operators.
// C#
// Make 2 anonymous classes with identical name/value pairs.
var firstCar = new { Color = "Bright Pink",
Make = "Saab", CurrentSpeed = 55 };
var secondCar = new { Color = "Bright Pink",
Make = "Saab", CurrentSpeed = 55 };

// Are they considered equal when using Equals()?  YES!
if (firstCar.Equals(secondCar))
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");

// Are they considered equal when using ==?  NO!
if (firstCar == secondCar)
Console.WriteLine("Same anonymous object!");
else
Console.WriteLine("Not the same anonymous object!");

// Are these objects the same underlying type?  YES!
if (firstCar.GetType().FullName == secondCar.GetType().FullName)
Console.WriteLine("We are both the same type!");
else
Console.WriteLine("We are different types!");



•        Anonymous types can be composed using additional anonymous types.
•        For example, consider the following entity which models a purchases order for a given automobile.
•        The screen shot is the result of calling ToString() on the purchaseItem object.
// C#
// Make an anonymous type which is composed of another.
var purchaseItem = new {
TimeBought = DateTime.Now,
ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55},
Price = 34.000};

' VB
' Make an anonymous type which is composed of another.
Dim purchaseItem = New With { _
.TimeBought = DateTime.Now, _
.ItemBought = New With {.Color = "Red", .Make = "Saab", .CurrentSpeed = 55}, _
.Price = 34.0}



•        When working with anonymous types, remember the following limitations:
•        You don’t control the name of the anonymous type.
•        Anonymous types always extend System.Object.
•        Anonymous types cannot support events, custom methods, custom overrides or overloaded operators.
•        Anonymous types are always implicitly sealed.
•        Anonymous types are always created using the default constructor.
•        Given these limitations, remember this feature is only useful when you wish to quickly model the ‘shape’
of a type, not its functionality.
•        Like many of the topics shown in this chapter, anonymous types are quite useful when working with
LINQ technologies.
Copyright (c) 2008.  Intertech, Inc. All Rights Reserved.  This information is to be used exclusively as an
online learning aid.  Any attempts to copy, reproduce, or use for training is strictly prohibited.
Object Initialization | Anonymous Types
Table of Contents
Courseware
Training Resources
Tutorials