4.1. Data TypesThe .NET Common Language Runtime (CLR) includes the Common Type System (CTS ), which defines the data types that are supported by the CLR. Each .NET-enabled language implements a subset of the CLR data types, although some languages implement all of them (Visual Basic does, starting in 2005). In .NET, data types are special classes and structures whose instances manipulate a data value that must fall within the limited range of the data type. For instance, the Byte data type can support and manage any 8-bit unsigned integer value, from 0 to 255. It allows no other data values outside of this defined subset, but it handles this subset extremely well. .NET provides data types for those subsets of data that programmers have found essential in software development. These data types make it possible to manipulate virtually any variation of data. For those instances where a predefined .NET data type will not meet your needs, you can use the predefined data types as building blocks to develop your own custom data management class. The .NET Framework implements nearly 20 of these essential core data types, most designed to manipulate integer or floating point numbers. The native VB data types are wrappers for the core data types. For instance, the VB Integer data type is a wrapper for the System.Int32 structure. One of the members of the Int32 structure is MaxValue, which returns the maximum numeric value allowed for this data type. Thus, even though MaxValue is not officially part of VB, the Integer data type's full dependence on the Int32 data type allows the following usage: Dim usesInt32 As Integer MsgBox(usesInt32.MaxValue) ' Displays 2147483647 Before the 2005 release of .NET, only some of the core .NET data types were implemented in Visual Basic. Yet even without specific VB wrappers, the earlier releases of VB.NET still provided access to the unwrapped data types. Since the core data types are simply classes and structures, they can be instantiated just like any other class or structure. 4.1.1. Value and Reference TypesData types in Visual Basic fall into two broad categories: (1) value types and (2) reference types . Value types and reference types differ primarily in how they are stored in memory. The memory allocated to a value type variable contains the actual value. In a statement such as: Dim simpleValue As Integer = 5 a memory location is set aside to hold the value of 5. In contrast, the memory storage allocated to a reference type variable stores another memory address location where the real data can be found. It's like a forwarding address at the post office. In a reference type declaration such as: Dim somewhereElse As New MyCustomClass the VB compiler creates an instance of the MyCustomClass class in memory and then sets the value of somewhereElse to the true memory address of that instance. If you are familiar with pointers in languages such as C++, this is Visual Basic's closest equivalent. In short, value type variables contain the data, and reference type variables point to the data. The distinction between value types and reference types has several consequences, one of which is in the way assignments work. Consider the following class, which has a single field: Public Class SimpleClass Public Age As Short End Class and an equivalent structure: Structure SimpleStruct Public Age As Short End Structure Classes are reference types, but structures are value types. The following code illustrates the difference in usage between the two similar yet different types. ' ----- Declare two of each type. Dim refType1 As SimpleClass Dim refType2 As SimpleClass Dim valType1 As SimpleStruct Dim valType2 As SimpleStruct ' ----- First, a demonstration of reference types. Setting ' refType2 = refType1 causes refType2 to *reference* ' the same memory location. Further changes made to ' members of refType1 will impact refType2, and vice ' versa. They share the same object instance. refType1 = New SimpleClass refType1.Age = 20 refType2 = refType1 refType2.Age = 30 Debug.WriteLine(refType1.Age) ' --> Shows 30 Debug.WriteLine(refType2.Age) ' --> Shows 30 ' ----- Now for value types. Setting valType2 = valType1 ' makes a *copy* of the members of valType1. Any ' further changes to the members of one variable ' will have *no* impact on the other. valType1 = New SimpleStruct valType1.Age = 20 valType2 = valType1 valType2.Age = 30 Debug.Writeline(valType1.Age) ' --> Shows 20 Debug.Writeline(valType2.Age) ' --> Shows 30 In a way, both assignments of one variable to the other did the same thing: they copied the value of the right-hand variable to the left-hand. But since the reference type, refType1, had a value of a memory address, that memory address was copied into refType2. Since both variables pointed to the same location in memory where the members were stored, both shared a common set of members. The assignment of the value type valType1 to valType2 also copied the value of the right-hand variable to the left hand. But the value of valType1 contained its actual members. A distinct copy of those members (only the Age member, in this case) was made for the separate use of valType2. To clear a reference type, set it to Nothing. Value types always have a value, even if it is zero; they cannot be set to Nothing. All of the core Visual Basic data types that manage numeric values (such as Integer and Double) are value types. The String data type is a reference type, but it acts like a value type. When you assign a string from one variable to another, you do not get a reference to the first string, as you would expect. That's because the implementation of the String data type always creates a completely new instance of the original string each time an assignment or change is made. 4.1.2. Visual Basic Data Types: A ReferenceVisual Basic implements all of the core .NET data types as of the 2005 edition of the language. These basic data types provide a broad range of features for managing all categories of data. The data types can be arranged into five groups by the type of data managed.
The remainder of this section includes definitions and commentary on each core data type supplied with the Visual Basic language. 4.1.2.1. Boolean data type
The Boolean data type supports only two possible values: TRue or False. The VB keywords true and False are used to assign these values to a Boolean variable. You can also assign the result of any logical operation to a Boolean variable. When a numeric value is converted to Boolean, any nonzero value is converted to true, and zero is converted to False. In the other direction, False is converted to zero, and true is converted to -1. (This differs from other .NET languages, which convert TRue to 1. Visual Basic uses -1 for reasons of backward compatibility. When sharing Boolean data between components built in different .NET languages, the .NET Framework automatically makes the correct adjustments according to the language in use.) 4.1.2.2. Byte data type
The Byte data type is the smallest unsigned integer data type supported by Visual Basic. While its range is small, it is especially useful when working with raw binary data. 4.1.2.3. Char data type
The Char data type stores a single 16-bit Unicode character. All characters in .NET are 16 bits in length, which is sufficient to support double-byte character set (DBCS) languages, such as Japanese. There was no equivalent to the Char data type in pre-.NET versions of Visual Basic. When using a literal Char value, append the single letter "c" to the value. Dim singleLetter As Char = "A"c A String variable containing a single character is not the same as a Char variable holding that same single character. They are distinct data types, and an explicit conversion is required to move data between the two types (when Option Strict is enabled). 4.1.2.4. Date data type
Date values are stored as IEEE 64-bit long integers that can represent dates in the range January 1, 1 to December 31, 9999, and times from 0:00:00 to 23:59:59. The actual value is stored internally as the number of "ticks" since midnight on January 1, 1 AD. Each tick represents 100 nanoseconds. Literal dates must be enclosed in number signs (#). Dim independenceDay As Date = #7/4/1776# 4.1.2.5. Decimal data type
Values of the Decimal data type are stored as 96-bit signed integers, along with an internal scale factor ranging from 0 to 28, which is applied automatically. This provides a high level of mathematical accuracy for numbers in the valid range, especially currency values. Literal instances of Decimal data append the letter "D" or the character "@" to the end of the numeric value. Dim startingValue As Decimal = 123.45D Dim endingValue As Decimal = 543.21@ You can also use the "@" character to indicate that a declared variable is of type Decimal. Dim startingValue@ = 123.45D The MaxValue and MinValue members of the Decimal data type provide the range limits. In pre-.NET implementations of Visual Basic, the Decimal data type was not a true data type; it existed as a subtype to the Variant data type. The .NET version of the Decimal data type is a true data type implementation. 4.1.2.6. Double data type
Values of type Double are IEEE 64-bit (8-byte) double-precision signed floating point numbers. They include a large range but also experience some accuracy loss in certain calculations. Literal instances of Double data append the letter "R" or the character "#" to the end of the numeric value. Dim startingValue As Double = 123.45R Dim endingValue As Double = 543.21# You can also use the "#" character to indicate that a declared variable is of type Double. Dim startingValue# = 123.45R 4.1.2.7. Integer data type
The Integer data type is a 32-bit signed integer data type. This is the native word size in 32-bit processors, so its use can provide some performance enhancements over other integral data types on those processors. In pre-.NET versions of Visual Basic, the Integer data type was only 16 bits in size and had a smaller range. The .NET version of Visual Basic includes Short as its 16-bit signed data type. Literal instances of Integer data optionally append the letter "I" or the character "%" to the end of the numeric value. Dim startingValue As Integer = 123I Dim endingValue As Integer = 543% You can also use the "%" character to indicate that a declared variable is of type Integer. Dim startingValue% = 123I 4.1.2.8. Long data type
The Long data type is a 64-bit signed integer data type. In pre-.NET versions of Visual Basic, the Long data type was only 32 bits in size and had a smaller range. The .NET version of Visual Basic uses Integer as its 32-bit signed data type. Literal instances of Long data append the letter "L" or the character "&" to the end of the numeric value. Dim startingValue As Long = 123L Dim endingValue As Long = 543& You can also use the "&" character to indicate that a declared variable is of type Long. Dim startingValue& = 123L When using the "&" character to identify a Long literal, do not leave a space between the number and the "&" character, as the "&" character alone acts as the string concatenation operator. 4.1.2.9. Object data type
The Object data type is the universal data type; an Object variable can refer to (point to) data of any other data type. For instance, an Object can refer to Long values, String values, or any other class instance. Dim amazingVariable As Object amazingVariable = 123L amazingVariable = "Isn't it great?" amazingVariable = New MyCustomClass There is a performance penalty when using Object variables. Visual Basic cannot associate the true data's members with the Object variable at compile time; this linking has to be done at runtime, which increases the amount of code required to process object-related methods. This is referred to as late binding. Declaring objects as their true type results in early binding, where all member links are managed by the compiler. Code such as: Dim lateBound As Object . . . lateBound = New MyCustomClass lateBound.SomeMethod( ) requires the application to match up the lateBound variable with MyCustomClass's SomeMethod member at runtime. This is much less efficient than: Dim earlyBound As MyCustomClass . . . earlyBound = New MyCustomClass earlyBound.SomeMethod( ) In pre-.NET versions of Visual Basic, the VarType function identified the specific subtype of a Variant value. The VarType function still exists in .NET-enabled Visual Basic; it identifies the true type of the variable or value. The System.Object class (and by derivation, all classes in .NET) also includes a GetType method that returns information about the true type of the object. Although these tools work with any data type, they are especially useful with objects of type Object. 4.1.2.10. SByte data type
New in 2005. The SByte data type is the smallest signed integer data type supported by Visual Basic. It acts as the signed counterpart to the unsigned Byte data type. The SByte data type is one of four Visual Basic data types, added in the 2005 release of the language, that are not compliant with the minimal Common Language Specification. Components and applications using that standard may not be compatible with applications that use the SByte data type. 4.1.2.11. Short data type
The Short data type is a 16-bit signed integer data type. In pre-.NET versions of Visual Basic, the Integer data type was a 16-bit signed data type; the Short data type did not exist in Visual Basic before .NET. Literal instances of Short data append the letter "S" to the end of the numeric value. Dim startingValue As Short = 123S 4.1.2.12. Single data type
Values of type Single are IEEE 32-bit (4-byte) single-precision signed floating point numbers. They include a moderate range but also experience some accuracy loss in certain calculations. Literal instances of Single data append the letter "F" or the character "!" to the end of the numeric value. Dim startingValue As Single = 123.45F Dim endingValue As Single = 543.21! You can also use the "!" character to indicate that a declared variable is of type Single. Dim startingValue! = 123.45F 4.1.2.13. String data type
The String data type holds variable-length Unicode character strings of up to approximately 2 billion characters in length. All strings in .NET are immutable. Once a value is assigned to a string, it cannot be changed. When you modify the contents of a string, the String data type returns a new instance of a string with the modifications. A String variable containing a single character is not the same as a Char variable holding that same single character. They are distinct data types, and an explicit conversion is required to move data between the two types (when Option Strict is enabled). 4.1.2.14. UInteger data type
New in 2005. The UInteger data type is a 32-bit unsigned integer data type. It acts as the unsigned counterpart to the signed Integer data type. The UInteger data type is one of four Visual Basic data types, added in the 2005 release of the language, that are not compliant with the minimal Common Language Specification. Components and applications using that standard may not be compatible with applications that use the UInteger data type. 4.1.2.15. ULong data type
New in 2005. The ULong data type is a 64-bit unsigned integer data type. It acts as the unsigned counterpart to the signed Long data type. The ULong data type is one of four Visual Basic data types, added in the 2005 release of the language, that are not compliant with the minimal Common Language Specification. Components and applications using that standard may not be compatible with applications that use the ULong data type. 4.1.2.16. UShort data type
New in 2005. The UShort data type is a 16-bit unsigned integer data type. It acts as the unsigned counterpart to the signed Short data type. The UShort data type is one of four Visual Basic data types, added in the 2005 release of the language, that are not compliant with the minimal Common Language Specification. Components and applications using that standard may not be compatible with applications that use the UShort data type. 4.1.3. User-Defined Data TypesWhile individual variables can potentially meet all of your programming needs, it is often more productive to combine multiple basic data values into logical groups. These user-defined data types extend the basic data types with new types of your own choosing. Pre-.NET versions of Visual Basic supported user-defined data type creation through the Type statement. These structured types were simply groupings of variables with no functionality beyond the ability to set and retrieve the value of each type member. Visual Basic under the .NET Framework greatly expands this feature by allowing code into each structure, as well as other basic .NET elements. Visual Basic 6 types are replaced by the .NET concept of a Structure. Classes are the basic code and data containers in .NET. Structures are similar to classes, although they have certain limitations that don't apply to classes. One significant difference is that structures implement value types (inherited directly from System.ValueType), while classes implement reference types. To declare a structure, use the Structure statement: [Public|Private|Friend] Structure structureName member declarations End Structure The members of a structure can be fields, properties, methods, shared events, enumerations, or other nested structures. Each member must be declared with an access modifier: Public, Private, or Friend. The simplest and most common use of structures is to encapsulate related variables, or fields. For instance, a simple structure can be used to define demographic information for a person: Structure Person Public Name As String Public Address As String Public City As String Public State As String Public Zip As String Public Age As Short End Structure A standard declaration defines a variable of type Person: Dim onePerson As Person Members of the structure are accessed using the standard "dot" syntax that applies also to classes: onePerson.Name = "Beethoven" More complex structures may include members and properties: Public Structure NameAndState ' ----- Public and private fields. Public Name As String Private theState As String Public Function ShowAll( ) As String ' ----- A public method. Show all stored values. If (theState = "") And (Name = "") Then Return "<No Name> from <Nowhere>" ElseIf (theState = "") Then Return Name & " from <Nowhere>" ElseIf (Name = "") Then Return "<No Name> from " & theState Else Return Name & " from " & theState End If End Function Public Property State( ) As String ' ----- A public property. Limit state values. Get Return theState End Get Set(ByVal value As String) If (Len(value) = 2) Then theState = UCase(value) Else Throw New System.ArgumentException( _ "State limited to 2 characters.", "State") End If End Set End Property End Structure Instances of the structure can now be created and used just like classes: Dim onePerson As New NameAndState onePerson.Name = "Donna" onePerson.State = "CA" MsgBox(onePerson.ShowAll( )) Structures can be passed as arguments to functions or used as the return type of a function. Although structures are similar to classes, they do not support the following class features:
For a reference to the object-oriented terminology, see Chapter 3. 4.1.4. Data Type ConversionThe process of converting a value of one data type to another is called conversion or casting. A conversion can be applied to a literal value, variable, or expression of a given type. Visual Basic includes several conversion functions that cast data between the basic data types . Dim miniSize As Byte = 6 Dim superSize As Long superSize = CLng(miniSize) ' Convert Byte variable to Long superSize = CLng("12") ' Convert String literal to Long Casts and conversions can be widening or narrowing. A widening cast is one in which the conversion is to a target data type that can accommodate all possible values in the source data type, such as casting from Short to Integer or from Integer to Double. Data is never lost in widening casts. A narrowing cast is one in which the target data type cannot accommodate all possible values of the source data type. In this case, data may be lost, and the cast may not succeed. Visual Basic conversions are made in two ways: implicitly and explicitly. An implicit conversion is done by the compiler when circumstances warrant it (and it is legal). For instance, in the statements: Dim smallerData As Integer = 3948 Dim largerData As Long largerData = smallerData the smallerData value is automatically converted to the larger Long data type used by the largerData variable. The type of implicit conversion that the compiler will do depends in part on the setting of the OptionStrict statement. This statement appears at the top of a source code file, before any class-specific code. Option Strict {On | Off} If Option Strict is On, only widening casts can be implicit; narrowing casts such as: Dim smallerData As Integer Dim largerData As Long = 3948 smallerData = largerData generate a compile-time error due to the narrowing conversion, even though the sample data could easily fit in the destination variable. Explicit conversion is required. smallerData = CInt(largerData) Setting Option Strict to Off permits the implicit conversion, even though the conversion may fail. In addition to the Option Strict statement, Visual Basic also includes an Option Explicit statement that appears at the start of a source code file. Option Explicit {On | Off} When Option Explicit is On, all variables must be declared (using Dim or a similar declaring keyword) before use. When Option Explicit is Off, VB will automatically add a declaration at compile time for any variable name it encounters that does not already have a declaration. (It won't add new Dim statements to your source code; it will add the declarations silently during the compile process.) Turning this option Off can lead to esoteric bugs that are hard to locate. See the "Option Explicit Statement" entry in Chapter 12 for additional information. The default values for both Option Strict and Option Explicit can be set in the project's properties. Visual Basic includes conversion functions for the basic data types.
|