Take my data . . . please! Ha, ha, that one always cracks me up. But it's actually what I ask my Visual Basic application to do: take data from some source (keyboard, hard disk, Internet, etc.) and present it in some useful way. All programs I write will actively manage at least some data in memory. Each data value is stored in a specific area of the computer's memory, as determined by the Common Language Runtime (CLR). The statements in Visual Basic exist primarily to manage and manipulate this data in useful and complex ways.
All data managed by the CLR is stored in the computer's memory, with each data value separated and protected from all others. It's as if each data value had its own individual teacup, as in Figure 2-1.
Figure 2-1. All types of teacups and data
All data values managed by the CLR have content and type. Content is the actual data: the text string "abc," the number 5, a sales invoice, orange pekoe. Whatever you put in the teacup, that's the content. In some cases, .NET allows you to store absolutely nothing in the teacup (only for "reference" types).
Type indicates the kind of content stored in the teacup. In Figure 2-1, this is shown by the shape of each teacup. Each teacup has limits on the type of data that can be poured into the teacup: a text string, an integer number, a customer invoice.
Some basic data values, such as numbers and text strings, can be entered into your source code and used just as they are. For instance, the MsgBox procedure displays a window with a supplied text message. The statement:
MsgBox("The answer is " & 42)
includes a literal string, "The answer is," and a literal integer value, 42. (The "&" symbol is an operator that connects two values into a new string.) Literals are used once, and then they're gone. If I wanted to show the same "The answer is 42" message again, I would have to once again type the same literal values into a different part of the source code.
There are several types of basic literals supported by Visual Basic. String literals are always surrounded by quote marks. If you want to include a quote mark itself in the middle of a string, include two instead of one:
"This is ""literally"" an example."
String literals can be really, really long, up to about two billion characters in length; if you were to type just one character per second, it would take over 63 years to reach the maximum string length. Visual Basic also includes a character literal that is exactly one character in length; if you were to type just one character per second, well, never mind. These character literals are recognized by the "c" trailing after the string. The character literal "A" is entered as:
Date and time literals are surrounded by number signs instead of quote marks. The date or time (or both) that you include can be in any format recognized by Microsoft Windows in your specific region. If you are using Visual Studio, it will reformat your date when you type in the literal.
There are 11 different kinds of numeric data valuesboth integers and floating point valuesthat make up the "core" set of numeric teacups. And who needs more than 11? With these 11 teacups, you can manage numbers from zero all the way to 1x10300 and beyond. To use a numeric literal, type the number right in your code, like 27, or 3.1415926535. Visual Basic also lets you specify which of the 11 numeric teacups to use for a number, by appending a special character to the end of the number. Normally, 27 is an integer. To make it a currency-focused "decimal," append an @ sign:
When I talk about data types in full detail in Chapter 6, "Data and Data Types," I will list the different special characters, like @, that set the data type for literal numbers.
The fourth and final type of Visual Basic literal is the Boolean literal. Boolean values represent the simplest type of computer data: the bit. Boolean values are either true or false, on or off, yes or no, delicious or disgusting, cats or dogs, zero or non-zero. Booleans always represent any two opposite values or states. George Boole invented Boolean Algebra, a language he used to represent logic statements as mathematical equations. It just so happens that computers love Boolean Algebra. All of the basic operations of a computer, such as addition, are implemented using Boolean functionality.
Visual Basic includes the Boolean literals True and False. No quotes. No number signs. Just the words True or False. Question: Is Tim Patrick telling the truth about this? Answer:
In certain cases, you can treat numbers as Boolean values. I'll talk about it more later, but for now just know that False equates to zero (0), and True equates to everything else (although generally, 1 is used for "everything else").
Literal data values are all well and good, but they are useful only once, and then they're gone. Each time you want to use a literal value, you must retype it. It's as if the data values are stored in disposable cups instead of fine china teacups. And besides, only programmers enter literal values, not users, so they are of limited use in managing user data.
Variables are not simply disposable cups; they are reusable. You can keep putting the same type of tea over and over into the teacup. A string variable teacup can hold a string for reuse over and over. For instance, in this block of code, response holds the various strings assigned to it.
01 response = "A" 02 MsgBox("Give me an 'A'!") 03 MsgBox(response) 04 MsgBox("Give me another 'A'!") 05 MsgBox(response) 06 MsgBox("What's that spell?") 07 response = StrDup(2, "A") 08 MsgBox(response)
The variable response is loaded twice with two different strings: an "A" and then "AA." It keeps whatever value was last assigned to it; both lines 03 and 05 display "A" in a message box window. And you don't just have to assign literal strings to it; anything that generates a string can assign its result to response. Line 07 uses a built-in Visual Basic function, StrDup, to return the two-character string "AA" and assign it to response.
Using variables is a two-step process. First you must declare the variable, and then you assign a value to it. The Dim statement takes care of the declaration part; it lets you indicate both the name and the type of a variable. Its basic syntax is pretty straightforward:
Dim response As String
where response is the name of the variable, and String is its type. Assignment occurs using the "=" assignment operator:
response = "The answer"
A single variable can have new values assigned to it over and over again. For those times when you want your variable to have some specific value immediately upon declaration, you can combine declaration and assignment into a single statement:
Dim response As String = "The answer"
Of course, you're not just limited to a single declaration; you can create as many variables as you need in your code. Each one normally uses its own Dim statement:
Dim question As String Dim answer As String
These can also be combined into a single statement, although I think it's just plain ugly:
Dim question As String, answer As String
See, I told you it was ugly. This is just the start of what's possible with the Dim statement. I'll get into more details as the chapter progresses.
Value Types and Reference Types
I talked about value types and reference types in Chapter 1, "Introducing .NET." Value type variables store an actual value; the tea in a value type teacup is the content itself. All of the literal data values I mentioned previously, except for Strings, are value types.
Reference type variables store a "reference" to the actual data, data found somewhere else in memory. When you look into a reference type teacup, you have to read the tea leaves at the bottom to determine where the real data resides.
Reference types either have data or they don't. In the absence of data, a reference type has a value of Nothing, a Visual Basic keyword that indicates no data. Value types are never Nothing; they always contain some value, possibly the default value for that type (such as zero for numeric types).
The String data type is useful, but it's only one of the teacup shapes at your disposal. The .NET Framework defines several core data types. Each data type is implemented as a specific class within the System namespace. The most basic data type, a large teacup that can hold any type of data, is called Object. More than just an object, this is object with a capital O. In the .NET Class Library namespace hierarchy, it's located at System.Object. It's the mother of all classes in .NET; all other classes, structures, enumerations, delegates, and other types, no matter where they reside in the namespace, whether they are written by Microsoft or by you, all derive from System.Object. There's no getting around it; you cannot create a class that ultimately derives from anything else.
So, back to these "core" data types I've been hinting at. They match the four types of literal data values I listed before: strings, dates, numbers, and Boolean values. Table 2-1 lists these core data types. Each of these types also has a Visual Basic-specific name that you can (and should) use instead.
The Microsoft developers in charge of Visual Basic data types lucked out on that job because all core Visual Basic data types are simply wrappers for specific data types implemented by .NET. The Visual Basic names given for each of these core data types are fully interchangeable with the .NET names. For example, Integer is fully equivalent to System.Int32. In fact, when writing Visual Basic code, it is better to use the Visual Basic synonyms, because most Visual Basic developers expect these data type names in the code they read and write.
Except for Object and String, all of these data types are value types. All value types are derived from System.ValueType (which in turn derives from System.Object).
The SByte, UInteger, ULong, and UShort data types were added to Visual Basic with its 2005 release, although their System namespace equivalents have been in .NET since its inception. Unlike the other core data types, these four types are not "CLS-compliant"; that is, they cannot be used to interact with .NET components and languages that limit themselves to just the very core required features of .NET. Generally this is not much of a limitation, but be on your guard when working with third-party components or languages.
When I mentioned the need for declaration and assignment of variables, I was really focusing on value types. Reference types require one additional step: instantiation. Consider the following declaration statements:
Dim defaultValue As Integer Dim nonDefaultValue As Integer = 5 Dim defaultReference As Object
These lines declare three separate variables: two value types (the Integers) and one reference type (the Object). Although only one variable has an explicit data assignment, all three have actually been assigned something, either explicitly or implicitly. Let's look at those statements again and see what is truly being assigned to each variable.
Dim defaultValue As Integer = 0 Dim nonDefaultValue As Integer = 5 Dim defaultReference As Object = Nothing
Both declaration and assignment already occurred for all of the variables, just by using the Dim statement. The defaultValue variable, with its default assignment of zero, can be used immediately in equations. However, the reference type variable defaultReference is just an empty teacup, with no default data to manipulate. There are features in Visual Basic that let you compare a reference type with Nothing, and you could do this immediately, but it's not really data. And remember, variables live to manage data.
Reference data values need instantiation, and instantiation needs the New keyword.
Dim defaultReference As Object = New Object
Now defaultReference points to a real object; now the defaultReference teacup has something consumable inside of it, but because it is just System.Object, it doesn't have much in the way of flavor. Strings are a little more interesting, and they also have more interesting constructors.
As you may recall from way back in Chapter 1, a constructor is a block of initialization code that runs when you create a new data value or object. Some objects allow you to supply extra information to a constructor, additional information that is used in the initialization process. A default constructor doesn't allow you to supply any extra information; it just works on its own, initializing data like it was nobody's business. There is no limit on the number of constructors in a class, but each one must vary in the type of extra information passed to it.
So back to Strings. You would expect the default String constructor to create a blank, zero-length string:
Dim worldsMostBoringString As String = New String
But the String class doesn't have a default constructor. Instead, you initialize the string with a literal:
Dim worldsMostBoringString As String = ""
That's because Strings are treated specially by Visual Basic. String literals are actually instantiations of String data values; it's as if you created a new String instance using the System.String class. But String also has more interesting constructors. (I'll delve into the details of constructors in Chapters 6 and 8, "Classes and Inheritance.") One of the constructors creates a new String instance initialized with a specific character repeated a number of times. For instance, to create a String instance with a 25-character string of the letter M, use the following syntax:
Dim mmGood As String = New String("M"c, 25)
If you're going to use the same data type just after the As keyword that you use right after the New keyword, you can use a collapsed syntax.
Dim mmGood As New String("M"c, 25)
As with value types, you can also break the statement into distinct declaration and assignment statements.
Dim mmGood As String mmGood = New String("M"c, 25)
Literals don't change, but they can only be used once in your code. Constants are a cross between a literal and a variable; they have a single, never-changing value just like data literals, but they also have a name that can be reused over and over again, just like variables.
You declare constants using the Const keyword instead of the Dim keyword:
Const SpeedOfLight As Integer = 186000
Actual assignment of the value to the constant occurs in the statement itself, with the value following the = sign. Once your constant is declared and assigned, it's available for use in actual statements of your actual code:
MsgBox("Lightspeed in miles/second: " & SpeedOfLight)
Local Declaration and Fields
In the real world, there is some data that you need to keep private, for your use only. Your neighbors have other juicy bits of data and information that they share among themselves. And then there is public data that isn't hidden from anyone. But it's not just this way in the real world; the fake world of Visual Basic has different levels of access and privacy for your data.
A little later in the chapter, we'll see that your application's logic code will always appear in procedures, named blocks of source code. You declare local variables (and constants) in these same procedures when you need a short-lived and personal variable that is only for use within a single procedure. Other variables (and constants) can appear outside of procedures, but still within the context of a class or similar type. These fields, whether variable or constant, are immediately available to all of the different procedures that also call the current class home.
You define all local variables using the Dim keyword. The Dim statement works for field definitions, but it's more common to use special access modifier keywords instead. These modifiers determine what code can access the fields, from Private (only used by code inside of the class) to Public (also available outside of the class).
Private ForInClassUseOnly As Integer
There are five access modifiers in all. I'll talk more about them, and about fields in general, in Chapters 6 and 8.