Chapter 4
Visual Basic .NET Data Types and Features
So far we've used a few easy examples to understand how programs are created in Visual Basic .NET . As you've learned, you need to understand concepts such as object-oriented programming up front to work with the code that's generated in Visual Basic .NET—even to display and use a simple form.
Another concept you need to be sure you understand is data types. A data type is a blueprint for the layout of a section of memory. This blueprint determines the range of values the memory can store and the operations you can perform on the memory. Of course, every variable, array, constant, property, procedure argument, and procedure return value has a data type. You'll see shortly that understanding data types goes far beyond simple numeric types—it extends to every object.
Getting to Know Data Types
As you know, a variable is really the name of a memory location that is used to store data. When you dimension a variable, you give it a
Many classic Visual Basic programmers have had limited exposure to data types. These programmers occasionally use
Although the
Variant
type has valid uses such as holding a reference to an
Excel
spreadsheet object, the
Variant
type is usually the last refuge of a
Visual Basic .NET is far stricter about how you use variables. The value you assign to a variable must be assignment compatible with the variable's type. If you declare a variable to be an Integer , you can't automatically assign a Short value to it. Visual Basic .NET also disallows type coercion. Those of you who like to write code similar to myString = "The number is " + 10 will really need to pay attention.
Visual Basic .NET Data Types
Visual Basic .NET uses two types of
They are handled differently by the memory management system.
They test for equality differently.
They are
They are treated differently in assignment statements.
A variable is a value type if it holds its data within its own memory location. A reference type, on the other hand, contains a reference (or pointer ) to another memory location that contains the actual data. Value types include all numeric and binary data types, such as the Integer type, the Char type, and the Date type. Reference types include strings, arrays, and all classes. Consider the following code fragment:
Dim newEmp1 As New myClass() Dim newEmp2 As New myClass() Dim iInteger1 As Integer = 12 Dim iInteger2 As Integer = 12 MessageBox.Show(iInteger1.Equals(iInteger2).ToString) 'True MessageBox.Show(newEmp1.Equals(newEmp2).ToString) 'False newEmp2 = newEmp1 MessageBox.Show(newEmp1.Equals(newEmp2).ToString) 'True
This example has two value variables (
iInteger1
and
iInteger2
) and two reference variables (
newEmp1
and
newEmp2
). Both
iInteger1
and
iInteger2
are assigned the value 12. Obviously, these variables are equal because their data is equal, and the message box will display True. However, the two variables are separate and distinct because they occupy different memory locations. If we assigned 42 to
iInteger1
, the value of
iInteger2
would
Now examine the statements concerning the reference variables newEmp1 and newEmp2 . These variables are initially dimensioned to point to different instances of myClass , and the first message box will print False. Next, newEmp1 is assigned to newEmp2 . Because these variables are reference variables, they now point to the same object in the same memory location, as shown in Figure 4-1. If any data fields in newEmp1 are changed or modified, they are also modified in newEmp2 because both variables reference the same memory location.
Figure 4-1
Reference variables point to memory locations.
When two reference variables are checked for equality, the check is really to see whether both variables reference the same memory location. If they do, as shown in Figure 4-1, they are
Value Types
A value type is also considered a primitive type in the .NET Framework. (A primitive type is a data type that is natively supported by the compiler. All primitive types are value types.) Value types are always accessed directly. In fact, you can't create a reference to a value type. And unlike reference types, setting a value type to Null is not possible. Value types always hold a value, even if you haven't yet assigned one. When a value type variable is dimensioned, it's initialized to a value representative of its type. If you dimension an Integer variable and don't assign a value to it, the Visual Basic .NET compiler automatically initializes the variable to 0.
The Visual Basic primitive types are identified through keywords, which are really aliases for predefined structure types in the System namespace. This fact means that a primitive type and the structure type for which it's an alias are completely indistinguishable. The Visual Basic keyword Byte is exactly the same as System.Byte .
Value types are
sealed
, meaning that no other type can be derived from them. Each value type is allocated a specific,
|
Visual Basic Type |
.NET Runtime Type Structure |
Memory Storage Size |
Default Value |
Value Range |
|
Boolean |
System.Boolean |
4 bytes |
False |
True or False |
|
Byte |
System.Byte |
1 byte |
|
0 through 255 (unsigned) |
|
Char |
System.Char |
2 bytes |
Chr(0) |
0 through 65,535 (unsigned) |
|
Date |
System.DateTime |
8 bytes |
# 01/01/0001 12:00:00AM # |
January 1, 1 CE through December 31, 9999 |
|
Decimal |
System.Decimal |
12 bytes |
0D |
+/- 79,228,162,514,264,337,593,543, 950,335 with no decimal point; +/- 7.9228162514264337593543950 335 with 28 places to the right of the decimal; smallest nonzero number is +/- 0.0000000000000000000000000001 |
|
Double (double-precision floating-point) |
System.Double |
8 bytes |
0.0 |
- 1.79769313486231E308 through - 4.94065645841247E-324 for negative values; 4.94065645841247E-324 through 1.79769313486232E308 for positive values |
|
Integer |
System.Int32 |
4 bytes |
|
- 2,147,483,648 through 2,147,483,647 |
|
Long (long integer) |
System.Int64 |
8 bytes |
|
- 9,223,372,036,854,775,808 through 9,223,372,036,854,775,807 |
|
Short |
System.Int16 |
2 bytes |
|
- 32,768 through 32,767 |
|
Single (single-precision floating-point) |
System.Single |
4 bytes |
0.0 |
- 3.402823E38 through - 1.401298E-45 for negative values; 1.401298E-45 through 3.402823E38 for positive values |
|
Structure |
System.ValueType |
Even though some
|
|
|
|
|
The
Currency
data type in classic Visual Basic is obsolete in the .NET Framework. When dealing with
|
|
|
|
The
Structure
data type is a legacy data type; it's the Visual Basic .NET
Structure DriveInfo DriveNumber() As Short DriveType As String DriveSpace as Long AvailableSpace as Long End Structure
A
Structure
is treated as a single unit, although its members can be accessed individually.
Structures
have two limitations: they cannot explicitly inherit from another type (although they implicitly inherit the
Structures are frowned upon in object-oriented programming. A class can do everything that a Structure can do—and more—so you should use classes instead of Structures .
Reference Types
As I mentioned earlier, a reference variable points to the memory location of the variable's data. This arrangement allows the garbage collector to track an object flagged for deletion and free the object's memory when it's no longer needed.
A reference variable always contains a reference to an object of its type, or null (
Nothing
) if you haven't explicitly initialized the variable. (A null reference points to nothing. It's illegal to do anything with a null reference except assign it a
|
Visual Basic Type |
.NET Runtime Type Structure |
Memory Storage Size |
Value Range |
|
Object |
System.Object (class) |
4 bytes |
Varies |
|
String (variable-length) |
System.String (class) |
10 + (2 string length) bytes |
0 through approximately 2 billion Unicode
|
As you learned in Chapter 2, "Object-Oriented Programming in Visual Basic .NET," an object is an instantiation of a class, and an Object variable is a reference variable that holds a pointer to the actual object. The Object variable itself always consumes exactly 4 bytes because it's simply a pointer to the memory location where the object it points to is located.
Recall that when a reference variable is created, it's initialized to null. Because of this arrangement, you must be sure to assign an actual object to the variable before you try to use it. Consider the following example:
Sub main() Dim oMyObject As Object MessageBox.Show(oMyObject.GetType.ToString) End Sub
The compiler will not object (no pun intended) to code like this. However, when this code executes and innocently
Figure 4-2
Accessing a null reference variable causes a run-time error.
The
String
data type is a sequence of zero or more double-byte (16-bit) Unicode characters. The codes for Unicode characters range from 0 through 65,535. The first 128 (0–127) characters of the Unicode character set