Value and reference Types

Experienced developers generally consider integers, characters, Booleans, and strings to be the basic building blocks of any language. As noted above in .NET, all objects share a logical inheritance from the base Object class. One of the advantages of this common heritage is the capability to rely on certain common methods of every variable. Another is that this enables all of .NET to build on a common type system. Visual Basic builds on the common type system shared across .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 we 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:

V 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.

V 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, let's examine how the System.Drawing.Point structure is used. To do this, you'll create a new method called ValueType() within your ProVB_VS2010 application. This new private Sub will be called from the ButtonTest click event handler. The new method will have the following format:

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

TextBoxl.Text = "Pt Y = " & ptY.ToString() End Sub

Code snippet from Forml

The output from this operation will be {{X = 10, Y = 20}}, is shown in Figure 2-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. Altering the value of 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:

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") TextBoxl.Text = "objY = " & objY.ToString() End Sub

The output from this operation will be "Hello Test," as shown in Figure 2-3, not "Hello World". The previous example using points demonstrated that when one value type is assigned to another, the data stored on the stack is copied. Similarly, this example demonstrates that when objY is assigned to objX, the data associated with objX on the stack is copied to the data 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 the 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 has been overridden for strings (which perform a deep copy).

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, let's take a closer look at some of the most commonly used value types and learn how .NET works with them.

Was this article helpful?

0 0

Post a comment