Working With Visual Basic Types

Having introduced a combination of keywords and concepts for objects in Visual Basic, it is time to start exploring specific types. In order to ensure this is hands on, you need a project in Visual Studio 2012. The first chapter focused on Visual Studio 2012 and many of its features as your primary development tool. This chapter is much more focused on the Visual Basic language, and to limit its size you are going to reference the project created in the first chapter. As this chapter introduces some of the core types of Visual Basic classes provided by the .NET Framework, you will use the test code snippets from this chapter in that project.

You can create a new project based on the ProVB2012 project from Chapter 1 and use it to host the example snippets throughout this chapter. The code download for this chapter includes the final version of the samples in a project titled ProVB2012_Ch03. This means that as you progress through the chapter, you can either look in the sample download for the same code, or step-by-step build up your own copy of the sample, using the sample when something doesn't seem quite right in your own code. One change from the previous chapter's code is that the custom property and message box used in that chapter have already been removed from this project.

At this point, you have a display that allows you to show the results from various code snippets simply by updating the Text property on the TextBox1 control of your window. The display for the baseline Windows Form application is shown in Figure 3.1.

Figure 3.1 Baseline test frame

3.1

The baseline is simply a button to initiate the sample code combined with a text box. To test a snippet, you add a new method to MainWindow, and then call this method from the Click event handler for the button. The sample download shows these methods in place, and then when you are ready to test the next method, remove the single quote to activate that method. Once you are done with one sample, comment out that method call and move to the next.

Value and Reference Types

Experienced developers generally consider integers, characters, Booleans, and strings to be the basic building blocks of any language. As noted previously in .NET, all objects share a logical inheritance from the base Object class. This enables all of .NET to build on a common type system. As noted in Chapter 2, Visual Basic builds on the common type system shared across all .NET languages.

Because all data types are based on the core Object class, every variable you dimension can be assured of having a set of common characteristics. However, this logical inheritance does not require a common physical implementation for all variables. This is important because while everything in .NET is based on the Object class, under the covers .NET has two major implementations of types: value and reference.

For example, what most programmers consider to be some of the basic underlying types, such as Integer, Long, Character, and even Byte, are not implemented as classes. This is important, as you'll see when you look at boxing and the cost of transitioning between value types and reference types. The difference between value types and reference types is an underlying implementation difference:

  • Value types represent simple data storage located on the stack. The stack is used for items of a known size, so items on the stack can be retrieved faster than those on the managed heap.
  • Reference types are based on complex classes with implementation inheritance from their parent classes, and custom storage on the managed heap. The managed heap is optimized to support dynamic allocation of differently sized objects.

Note that the two implementations are stored in different portions of memory. As a result, value types and reference types are treated differently within assignment statements, and their memory management is handled differently. It is important to understand how these differences affect the software you will write in Visual Basic. Understanding the foundations of how data is manipulated in the .NET Framework will enable you to build more reliable and better-performing applications.

Consider the difference between the stack and the heap. The stack is a comparatively small memory area in which processes and threads store data of fixed size. An integer or decimal value needs the same number of bytes to store data, regardless of the actual value. This means that the location of such variables on the stack can be efficiently determined. (When a process needs to retrieve a variable, it has to search the stack. If the stack contained variables that had dynamic memory sizes, then such a search could take a long time.)

Reference types do not have a fixed size—a string can vary in size from two bytes to nearly all the memory available on a system. The dynamic size of reference types means that the data they contain is stored on the heap, rather than the stack. However, the address of the reference type (that is, the location of the data on the heap) does have a fixed size, and thus can be (and, in fact, is) stored on the stack. By storing a reference only to a custom allocation on the stack, the program as a whole runs much more quickly, as the process can rapidly locate the data associated with a variable.

Storing the data contained in fixed and dynamically sized variables in different places results in differences in the way variables behave. Rather than limit this discussion to the most basic of types in .NET, this difference can be illustrated by comparing the behavior of the System.Drawing.Point structure (a value type) and the System.Text.StringBuilder class (a reference type).

The Point structure is used as part of the .NET graphics library, which is part of the System.Drawing namespace. The StringBuilder class is part of the System.Text namespace and is used to improve performance when you're editing strings.

First, you will examine how the System.Drawing.Point structure is used. To do this, you'll create a new method called ValueType() within your ProVB2012_Ch03 application. This new private Sub will be called from the ButtonTest click event handler. The new method will have the following format (code file: MainWindow.xaml.vb):

Private Sub ValueType()
    Dim ptX As System.Drawing.Point = New System.Drawing.Point(10, 20)
    Dim ptY As System.Drawing.Point
    ptY = ptX
    ptX.X = 200
    TextBox1.Text = "Pt Y = " & ptY.ToString()
End Sub

The output from this operation will be Pt Y = {{X = 10, Y = 20}}, is shown in Figure 3.2.

Figure 3.2 Output Pt Y value

3.2

When the code copies ptX into ptY, the data contained in ptX is copied into the location on the stack associated with ptY. Later, when the value of ptX changes, only the memory on the stack associated with ptX is altered. Changing ptX has no effect on ptY. This is not the case with reference types. Consider the following code, a new method called RefType, which uses the System.Text.StringBuilder class (code file: MainWindow.xaml.vb):

Private Sub RefType()
    Dim objX As System.Text.StringBuilder = 
            New System.Text.StringBuilder("Hello World")
    Dim objY As System.Text.StringBuilder
    objY = objX
    objX.Replace("World", "Test")
    TextBox1.Text = "objY = " & objY.ToString()
End Sub

The output from this operation will be ObjY = Hello Test, as shown in Figure 3.3, not ObjY = Hello World.

Figure 3.3 Output of the ObjY value

3.3

The first example using point values demonstrated that when one value type is assigned to another, the data stored on the stack is copied. This example demonstrates that when objY is assigned to objX, the address associated with objX on the stack is associated with objY on the stack. However, what is copied in this case isn't the actual data, but rather the address on the managed heap where the data is actually located. This means that objY and objX now reference the same data. When that data on the heap is changed, the data associated with every variable that holds a reference to that memory is changed. This is the default behavior of reference types, and is known as a shallow copy. Later in this chapter, you'll see how this behavior varies for strings.

The differences between value types and reference types go beyond how they behave when copied, and later in this chapter you'll encounter some of the other features provided by objects. First, though, take a closer look at some of the most commonly used value types and learn how .NET works with them.

Primitive Types

Visual Basic, in common with other development languages, has a group of elements such as integers and strings that are termed primitive types. These primitive types are identified by keywords such as String, Long, and Integer, which are aliases for types defined by the .NET class library. This means that the line

Dim i As Long

is equivalent to the line

im i As System.Int64

The reason why these two different declarations are available has to do with long-term planning for your application. In most cases (such as when Visual Basic transitioned to .NET), you want to use the Short, Integer, and Long designations. If at some point your system decides to allow an integer to hold a larger 64 bit value you don't need to change your code.

On the other hand Int16, Int32, and Int64 specify a physical implementation; therefore, if your code is someday migrated to a version of .NET that maps the Integer value to Int64, then those values defined as Integer will reflect the new larger capacity, while those declared as Int32 will not. This could be important if your code were manipulating part of an interface where changing the physical size of the value could break the interface.

Table 3.1 lists the primitive types that Visual Basic 2012 defines, and the structures or classes to which they map:

Table 3.1 Primitive Types in .NET

Primitive Type .NET Class or Structure
Byte System.Byte (structure)
Short System.Int16 (structure)
Integer System.Int32 (structure)
Long System.Int64 (structure)
Single System.Single (structure)
Double System.Double (structure)
Decimal System.Decimal (structure)
Boolean System.Boolean (structure)
Date System.DateTime (structure)
Char System.Char (structure)
String System.String (class)

Note
The String primitive type stands out from the other primitives. Strings are implemented as a class, not a structure. More important, strings are the one primitive type that is a reference type.

You can perform certain operations on primitive types that you can't on other types. For example, you can assign a value to a primitive type using a literal:

Dim i As Integer = 32
Dim str As String = "Hello"

It's also possible to declare a primitive type as a constant using the Const keyword, as shown here:

Dim Const str As String = "Hello"

The value of the variable str in the preceding line of code cannot be changed elsewhere in the application containing this code at run time. These two simple examples illustrate the key properties of primitive types. As noted, most primitive types are, in fact, value types. The next step is to take a look at core language commands that enable you to operate on these variables.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset