VB 2008 introduced a new way to hydrate the state of a new class or structure variable termed object initializer syntax. Using this technique, it is possible to create a new type variable and assign a slew of properties and/or public fields in a few lines of code. Syntactically, an object initializer consists of a comma-delimited list of specified values, enclosed by the { and } tokens, preceded with the With keyword. Each member in the initialization list maps to the name of a public field or public property of the object being initialized.
Now, consider the following Point type:
1: Public Class Point
2: Private xPos As Integer, yPos As Integer
3:
4: Public Sub New(ByVal x As Integer, ByVal y As Integer)
5: xPos = x
6: yPos = y
7: End Sub
8: Public Sub New()
9: End Sub
10:
11: Public Property X() As Integer
12: Get
13: Return xPos
14: End Get
15: Set (ByVal value As Integer)
16: xPos = value
17: End Set
18: End Property
19: Public Property Y() As Integer
20: Get
21: Return yPos
22: End Get
23: Set (ByVal value As Integer)
24: yPos = value
25: End Set
26: End Property
27:
28: Public Overrides Function ToString() As String
29: Return String.Format("[{0}, {1}]", xPos, yPos)
30: End Function
31: End Class
We could now make Points using any of the following approaches:
1: Sub Main()
2: Console.WriteLine("***** Fun with Object Init Syntax *****")
3: ' Make a Point by setting each property manually...
4: Dim firstPoint As New Point()
5: firstPoint.X = 10
6: firstPoint.Y = 10
7: Console.WriteLine(firstPoint.ToString())
8:
9: ' ...or make a Point via a custom constructor...
10: Dim anotherPoint As New Point(20, 20)
11: Console.WriteLine(anotherPoint.ToString())
12:
13: ' ...or make a Point types using the new object init syntax.
14: Dim finalPoint As New Point With { .X = 30, .Y = 30 }
15: Console.WriteLine(finalPoint.ToString())
16:
17: Console.ReadLine()
18: End Sub
The final Point variable is not making use of a custom type constructor (as one might do traditionally), but are rather setting values to the public X and Y properties. Behind the scenes, the type?s default constructor is invoked, followed by setting the values to the specified properties. To this end, finalPoint is just shorthand notations for the syntax used to create the firstPoint variable (going property by property).
Now recall that this same syntax can be used to set public fields of a type, which Point currently does not support. However, for the sake of argument, assume that the xPos and yPos member variables have been declared publicly. We could now set values to these fields as follows:
1: Dim p As New Point With {.xPos = 2, .yPos = 3}
Given that Point now has four public members, the following syntax is also legal. However, try to figure out the actual final values of xPos and yPos:
1: Dim p As New Point With {.xPos = 2, .yPos = 3, .X = 900}
As you might guess, xPos is set to 900, while yPos is the value 3. From this, you can correctly infer that object initialization is performed in a left-to-right manner. To clarify, the previous initialization of p using standard object constructor syntax would appear as follows:
1: Dim p As New Point()
2: p.xPos = 2
3: p.yPos = 3
4: p.X = 900
Now assume we now have a Rectangle class, which makes use of the Point type to represent its upper-left/bottom-right coordinates:
1: Public Class Rectangle
2: Private m_topLeft As New Point()
3: Private m_bottomRight As New Point()
4:
5: Public Property TopLeft() As Point
6: Get
7: Return m_topLeft
8: End Get
9: Set (ByVal value As Point)
10: m_topLeft = value
11: End Set
12: End Property
13: Public Property BottomRight() As Point
14: Get
15: Return m_bottomRight
16: End Get
17: Set (ByVal value As Point)
18: m_bottomRight = value
19: End Set
20: End Property
21:
22: Public Overrides Function ToString() As String
23: Return String.Format("[TopLeft: {0}, {1}, BottomRight: {2}, {3}]", _
24: m_topLeft.X, m_topLeft.Y, m_bottomRight.X, m_bottomRight.Y)
25: End Function
26: End Class
Using object initialization syntax, we could create a new Rectangle type and set the inner Points as follows:
1: ' Create and initialize a Rectangle.
2: Dim myRect As New Rectangle() With
3: {
4: .TopLeft = New Point() With { .X = 10, .Y = 10 },
5: .BottomRight = New Point() With { .X = 200, .Y = 200}
6: }
Although this VB syntax has been supported since .NET 3.5, it can be easy to forget about this streamlined way to hydrate objects and fallback on older techniques.
Again, the benefit of this new syntax is that it basically decreases the number of keystrokes (assuming there is not a suitable constructor). Here is the traditional approach to establishing a similar Rectangle:
1: ' Old-school approach.
2: Dim r As New Rectangle()
3: Dim p1 As New Point()
4: p1.X = 10
5: p1.Y = 10
6: r.TopLeft = p1
7: Dim p2 As New Point()
8: p2.X = 200
9: p2.Y = 200
10: r.BottomRight = p2
Happy coding!