The syntax for declaring a structure is almost identical to that for a class:
[attributes] [access-modifiers] Structure identifier [Implements4 interface-list] structure-members End Structure
Attributes are discussed in Chapter 18. Access modifiers (Public, Private, etc.) work just as they do with classes. (See Chapter 5 for a discussion of access modifiers.) The keyword Structure is followed by an identifier (the name of the structure). The optional interface-list is explained in Chapter 8. Within the body of the structure, you define fields and methods, also called the structure members, just as you do in a class.
Example 7-1 defines a structure named Location to hold x,y coordinates of an object displayed on the screen.
Option Strict On Imports System Namespace StructureDemonstration ' declare a Structure named Location Public Structure Location ' the structure has private data Private myXVal As Integer Private myYVal As Integer ' constructor Public Sub New( _ ByVal xCoordinate As Integer, ByVal yCoordinate As Integer) myXVal = xCoordinate myYVal = yCoordinate End Sub 'New ' property Public Property XVal( ) As Integer Get Return myXVal End Get Set(ByVal Value As Integer) myXVal = Value End Set End Property Public Property YVal( ) As Integer Get Return myYVal End Get Set(ByVal Value As Integer) myYVal = Value End Set End Property ' Display the structure as a String Public Overrides Function ToString( ) As String Return String.Format("{0}, {1}", xVal, yVal) End Function 'ToString End Structure 'Location Class Tester Public Sub Run( ) ' create an instance of the structure Dim loc1 As New Location(200, 300) ' display the values in the structure Console.WriteLine("Loc1 location: {0}", loc1) ' invoke the default constructor Dim loc2 As New Location( ) Console.WriteLine("Loc2 location: {0}", loc2) ' pass the structure to a method myFunc(loc1) ' redisplay the values in the structure Console.WriteLine("Loc1 location: {0}", loc1) End Sub 'Run ' method takes a structure as a parameter Public Sub myFunc(ByVal loc As Location) ' modify the values through the properties loc.XVal = 50 loc.YVal = 100 Console.WriteLine("Loc1 location: {0}", loc) End Sub 'myFunc Shared Sub Main( ) Dim t As New Tester( ) t.Run( ) End Sub 'Main End Class 'Tester End Namespace 'StructureDemonstration Output: Loc1 location: 200, 300 Loc2 location: 0, 0 Loc1 location: 50, 100 Loc1 location: 200, 300
The Location structure is defined as public, much as you might define a class.
Public Structure Location ' the structure has private data Private myXVal As Integer Private myYVal As Integer
As with a class, you can define a constructor and properties for the structure. For example, you might create integer member variables myXVal and myYVal, and then provide public properties for them named XVal and YVal (see Chapter 5):
' constructor Public Sub New( _ ByVal xCoordinate As Integer, ByVal yCoordinate As Integer) myXVal = xCoordinate myYVal = yCoordinate End Sub 'New Public Property XVal( ) As Integer Get Return myXVal End Get Set(ByVal Value As Integer) myXVal = Value End Set End Property Public Property YVal( ) As Integer Get Return myYVal End Get Set(ByVal Value As Integer) myYVal = Value End Set End Property
There is no difference in the way you create constructors and properties in structures and the way you do so in classes. However, you are not permitted to create a custom default constructor for a structure. That is, you cannot write a constructor with no parameters. Thus the following code would not compile:
' won't compile - no custom default ' constructors for structures Public Sub New( ) xVal = 5 yVal = 10 End Sub 'New
Instead, the compiler creates a default constructor for you (whether or not you create other constructors), and that default constructor initializes all the member values to their default values (e.g., integers are initialized to zero).
The Run( ) method of the Tester class creates an instance of the Location structure named loc1, passing in the initial x,y coordinates of 200,300:
Dim loc1 As New Location(200, 300)
Loc1 is then passed to WriteLine( ) to display the x,y values:
Console.WriteLine("Loc1 location: {0}", loc1)
When you pass the loc1 object to Console.WriteLine( ), WriteLine( ) automatically invokes the overridable ToString( ) method on the object. Thus, Location.ToString( ) is invoked, which displays the x and y coordinates of the loc1 object:
Loc1 location: 200, 300
Before modifying the values in loc1, the example creates a second instance of the Location structure, named loc2, and displays its values:
Dim loc2 As New Location( ) Console.WriteLine("Loc2 location: {0}", loc2)
The creation of loc2 invokes the default constructor (note that no parameters are passed in). The output shows that the compiler-provided default constructor initialized the member variables to default values.
Loc2 location: 0, 0
You next pass your first structure, loc1, whose values are 200,300, to a method, myFunc( ). In that method, the parameter is a Location object named loc. Within the myFunc( ) method, the XVal property is used to set the x coordinate to 50, and the YVal property is used to set the y coordinate to 100; then the new value is displayed using WriteLine( ):
Public Sub myFunc(ByVal loc As Location) ' modify the values through the properties loc.XVal = 50 loc.YVal = 100 Console.WriteLine("Loc1 location: {0}", loc) End Sub 'myFunc
As expected, the results show the modification:
Loc1 location: 50, 100
When you return to the calling method (Run( )), the values of loc1 are displayed, showing they are unchanged from before the call to myFunc( ):
Loc1 location: 200, 300
When you passed loc1 to myFunc( ), the structure was passed by value (structures, like the intrinsic types, are value types). A copy was made, and it was on that copy that you changed the values to 50 and 100. The original Location structure (loc1) was unaffected by the changes made within myFunc( ).
Unlike classes, structures do not support inheritance. Structures implicitly derive from Object (as do all types in VB.NET, including the built-in types) but cannot inherit from any other class or structure. Structures are also implicitly not-inheritable (that is, no class or structure can derive from a structure). See Chapter 6 for a discussion of inheritance and not-inheritable classes.
You cannot initialize an instance field in a structure. Thus, it is illegal to write:
Private xVal As Integer = 50 Private yVal As Integer = 100
though this kind of initialization is perfectly legal in a class. You must instead set the value of your member fields in the body of the constructor. As noted earlier, the default constructor (provided by the compiler) will set all the member variables to their default value.
Structures are designed to be simple and lightweight. While private member data promotes data hiding and encapsulation, some programmers feel it is overkill for structures. They make the member data public, thus simplifying the implementation of the structure. Other programmers feel that properties provide a clean and simple interface, and that good programming practice demands data hiding even with simple lightweight objects. Which you choose is a matter of design philosophy; the language will support either approach.
Top |