Previous section   Next section

7.1 Defining a Structure

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.

Example 7-1. Creating a structure
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( ).

7.1.1 No Inheritance

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.

7.1.2 No Initialization

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.

7.1.3 Public Member Data?

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.


  Previous section   Next section
Top