Variables hold values in memory so a program can manipulate them. Different kinds of variables hold different types of data: numbers, text, pictures, Halo scores, even complex groups of data such as employee records.
In this lesson you learn what variables are and how to use them. You learn how to define variables, put data in them, and use them to perform simple calculations.
Technically speaking, a variable is a named piece of memory that can hold some data of a specific type. For example, a program might allocate 4 bytes of memory to store an integer. You might name this memory "payoffs" so you can easily refer to it in the program's code.
Less technically, you can think of a variable as a named place to put a piece of data. The program's code can use variables to store values and perform calculations. For example, a program might store two values in variables, add the values together, and store the result in a third variable.
Every variable has a particular data type that determines the kind of data that it can hold. In general, you cannot place data of one type in a variable of another. For example, if price
is a variable that can hold a number in dollars and cents, you cannot put the string "Hello" in it.
If you like, you can think of a variable as an envelope with a name written on the outside that can hold some data, but each type of data requires a differently shaped envelope. Integers need relatively small envelopes, singles (which hold numbers with decimal points) need envelopes that are long and thin, and strings need big fat envelopes.
Sometimes the line between two data types is a bit fuzzy. For example, if a variable should hold a number, you cannot put in the string "ten." The fact that "ten" is a number is obvious to a human but not to a Visual Basic program.
You can't even place a string containing the characters "10" in a variable that holds a number. Though it should be obvious to just about anyone that "10" is a number, Visual Basic just knows it's a string containing the two characters 1 and 0; it doesn't try to determine that the characters in the string represent a number.
Programs often need to convert a value from one data type to another (particularly switching between strings and numbers), so Visual Basic provides an assortment of data conversion functions to do just that. The section "Type Conversions" later in this lesson describes these functions.
Table 11-1 summarizes Visual Basic's built-in data types. The signed types can store values that are positive or negative, whereas the unsigned types can hold only positive values.
Table 11.1. TABLE 11-1
DATA TYPE | MEANING | RANGE |
---|---|---|
Byte | 0 to 255 | |
Signed byte | −128 to 127 | |
Small signed integer | −32,768 to 32,767 | |
Unsigned short | 0 to 65,535 | |
Integer | −2,147,483,648 to 2,147,483,647 | |
Unsigned integer | 0 to 4,294,967,295 | |
Long integer | −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | |
Unsigned long | 0 to 18,446,744,073,709,551,615 | |
Single-precision floating point | Roughly −3.4e38 to 3.4e38 | |
Double-precision floating point | Roughly −1.8e308 to 1.8e308 | |
Higher precision and smaller range than floating-point types | See the following section, "Single, Double, and Decimal Data Types." | |
Character | A single Unicode character. (Unicode characters use 16 bits to hold data for text in scripts such as Arabic, Cyrillic, Greek, and Thai.) | |
Text | A string of Unicode characters | |
Boolean | Can be | |
An object | Can point to almost anything |
Some of these data types are a bit confusing but the most common data types (Integer, Long, Single, Double
, and String
) are fairly straightforward, and they are the focus of most of this lesson. Before moving on to further details, however, it's worth spending a little time comparing the Single, Double
, and Decimal
data types.
The computer represents values of every type in binary using bits and bytes, so some values don't fit perfectly in a particular data type. In particular, real numbers such as 1/7 don't have exact binary representations, so the Single, Double
, and Decimal
data types often introduce slight rounding errors.
For example, a Single
represents 1/7 as approximately 0.142857149. Usually the fact that this is not exactly 1/7 isn't a problem, but once in a while if you compare two Single
values to determine whether they are exactly equal, rounding errors make them appear to be different even though they should be the same.
The Decimal
data type helps reduce this problem for decimal values such as 1.5 (but not non-decimal real values such as 1/7) by storing an exact representation of the decimal value. Instead of storing a value as a binary number the way Single
and Double
do, Decimal
stores the number's digits and its exponent separately as integral data types with no rounding. That lets it hold 28 or 29 significant digits (depending on the exact value) for numbers between roughly −7.9e28 and 7.9e28.
Note that rounding errors can still occur when you combine Decimal
values. For example, if you add 1×1028 plus 1×10−28, the result would have more than the 28 or 29 significant digits that a Decimal
can provide so it rounds off to 1×1028.
The moral of the story is that you should always use the Decimal
data type for values when you need great accuracy and the values won't get truly enormous. In particular, you should always use Decimal
for currency values. Unless you're Bill Gates' much richer uncle, you'll never get close to the largest value a Decimal
can represent, and the extra precision can prevent rounding errors during some fairly complex calculations.
Another interesting feature of the Decimal
type is that, due to the way it stores its significant digits, it remembers zeros on the right. For example, if you add the values 1.35 and 1.65 as Singles
, you get the value 3. In contrast, if you add the same values as Decimals
, you get 3.00. The Decimal
result remembers that you were working with two digits to the right of the decimal point so it stores the result that way, too.
To declare a variable in Visual Basic code, use the Dim
keyword, followed by the name that you want to give the variable, the As
keyword, and the data type. For example, the following code creates a variable named numMistakes
. The variable's data type is Integer
, so it can hold an integer between −2,147,483,648 and 2,147,483,647.
Dim numMistakes As Integer
After you declare the variable, you can use the equals symbol to assign a value to a variable. For example, the following code sets numMistakes
to 1337
:
numMistakes = 1337
As an added convenience, you can declare a variable and give it a value at the same time:
Dim numMistakes As Integer = 1337
You can declare several variables of the same type all at once by separating them with commas as in the following code:
Dim x, y, z As Single
A literal value is a piece of data stuck right in the code. For example, in the following statement, numMistakes
is a variable and 1337
is a literal integer value:
Dim numMistakes As Integer = 1337
Usually Visual Basic is pretty smart about using the correct data types for literal values. For example, in the preceding statement Visual Basic knows that numMistakes
is an integer and 1337
is an integer, so it can safely put an integer value in an integer variable.
You should use double quotes to surround or delimit Strings
and Chars
, as in the following code:
Dim firstName As String = "William" Dim lastName As String = "Gates" Dim middleInitial As Char = "H"
You should use number signs (#) to delimit dates and times, as shown here:
Dim birthday As Date = #8/20/2011# Dim partyTime As DateTime = #5:30:00 PM#
You must use American formats in date and time literals in your code even if your system uses other settings such as the day/month/year date format. Visual Basic code understands only these formats.
As I mentioned earlier, you can think of a variable as an envelope of a certain size that can only hold one kind of data. For example, you can't put a string value in an Integer
variable.
However, programs often do need to store one kind of value in a different kind of variable. For example, suppose a user wants to buy five rare Pokémon cards for $1.50 each. Before it can calculate the total cost, the program needs to get the values 5 and 1.50 into numeric variables such as Integers
or Decimals
.
Other times a program may have a value stored in a variable of one type, such as Integer
, and need to copy it into a variable of another type, such as Double
.
In these cases, the program must perform a type conversion to convert a value from one data type to another. Your program can use one of two basic types of conversion: implicit or explicit.
In an implicit type conversion, Visual Basic converts a value from one type to another automatically, often without you even being aware of it.
Visual Basic will convert any data from one type to another if it understands how to make such a conversion. For example, if you assign a Single
variable equal to an Integer
value, Visual Basic will very happily convert the Integer
into a Single
.
In fact, any valid Integer
value will fit without any loss of precision in a Single
variable so this is even a safe type conversion.
Returning to the earlier analogy of data types as envelopes, you might imagine Integer
as a thin envelope because it holds a relatively small range of values. In contrast, Single
can hold a much bigger range of values so it is a wider envelope. Keeping this analogy in mind, converting an Integer
into a Single
is called a widening conversion because you are going from a relatively thin data type to a wider one.
In contrast, suppose you need to convert a Single
value into an Integer
. This is called a narrowing conversion because you are going from a "wider" data type to a "narrower" one. In this case, some precision may be lost. For example, if you store the Single
value 1.23 in an Integer
, you get the result 1.
Visual Basic is quite creative at both widening and narrowing implicit conversions and will perform them automatically if necessary. For example, all of the following conversions are legal in a Visual Basic program:
Dim i As Integer Dim s As Single ' Copy the Integer value 123 into a Single. i = 123 s = i ' Copy the Single value 1.23 into an Integer (giving 1). s = 1.23 i = s ' Copying strings holding numbers into numeric variables. i = "321" s = "3.21" ' Set a Boolean from a string. Dim ready As Boolean = "True"
There are limits to what Visual Basic can do, however. For example, it can convert the string values True
and False
into the Boolean
data type but it doesn't understand Yes, No, Sure, Negatory
, or any other string value.
For simple programs, implicit conversions are typically fine and they do the right thing, but it's not always obvious where they occur and that can sometimes lead to problems.
For example, suppose a program contains the following statement:
total = subtotal
This may look like a perfectly safe statement but suppose total
is an Integer
and subtotal
is a Long
. In that case, this is a narrowing conversion because not all Long
values can fit in an Integer
, so the program may sometimes crash. To make matters worse, many Long
values do fit so you may not notice the problem until specific inputs make the value really large. For example, if subtotal
is the number of items in a customer's order, then it will probably fit in an Integer
; but, if it represents the total population of the world, then it won't fit in an Integer
.
For an even trickier example, suppose the user enters a purchase quantity in a TextBox
. If the user enters a number such as "10," then the following code works:
Dim quantity As Integer = txtQuantity.Text
However, if the user enters "ten," the program crashes with the error message "Conversion from string "ten" to type 'Integer' is not valid."
Possibly even more troubling, if the user enters the value 12.34, the program does not crash! Instead, it silently converts the string into the Double
value 12.34 and then converts that into an Integer
. You might prefer to have the program warn you somehow that the user didn't enter an Integer
, rather than silently treat it like one.
One way you can minimize these unexpected problems is to prohibit implicit narrowing conversions. Then you can't give an Integer
variable a Long
value, and you can't save a String
value into an Integer
.
To prohibit implicit narrowing conversions, add the following line to the very top of a code module:
Option Strict On
Prohibiting implicit narrowing conversions prevents some kinds of errors but what if you really need to perform a narrowing conversion? For example, suppose the user enters an order quantity in a TextBox
. How do you convert the value into an Integer
so you can perform calculations?
The answer is to use an explicit conversion. In an explicit conversion, you use code to convert the value. This works more or less the same way an implicit conversion would work except you are doing it on purpose. By making an explicit conversion, you are acknowledging that you know there's a risk and you are willing to take responsibility.
There are five main ways you can perform an explicit conversion: using Visual Basic conversion functions, using CType
, using DirectCast
and TryCast
, using Convert
, and using Parsing
.
Visual Basic provides a set of functions for explicitly converting values into new data types. For example, the following code uses the CDec
function to convert the text entered by the user in the txtCost TextBox
into a Decimal
and then saves it in the variable cost
:
Dim cost As Decimal = CDec(txtCost.Text)
Table 11-2 lists Visual Basic's conversion functions.
Table 11.2. TABLE 11-2
FUNCTION | CONVERTS TO |
---|---|
| Boolean |
| Byte |
| Char |
| Date |
| Double |
| Decimal |
| Integer |
| Long |
| Object |
| Short |
| Single |
| String |
The integer functions round floating-point values off to the nearest integer. For example, CInt(1.7)
returns 2.
Another function, Int
, truncates floating-point values. For example, Int(1.7)
returns 1. Note that the result returned by Int
has the same data type as its parameter; so, for example, if you pass Int
a Double
, it returns a Double
. Often you will want to use CInt
to convert that result into an Integer
.
The Fix
function is similar to Int
except it truncates towards 0. That means for negative numbers Int
decreases the value (Int(-8.5) = −9.0
) but Fix
increases the value (Fix(-8.5) = −8.0
).
Each of these functions causes an error if it cannot convert the value. For example, ("1x3")
causes an error because "1x3" is not a valid number.
Visual Basic also includes a special-purpose Val
function that converts a value into a Double
. If Val
cannot convert the value into a Double
, it silently returns 0. For example, if you use Val
to convert a value typed by the user into a number and the user types "six," then Val
ignores the error and returns 0.
This makes Val
useful for converting values typed by the user into numbers if 0 is a reasonable default value. If 0 is not a reasonable default value, then your program should use some other method for converting the string into a number, such as parsing, which is described shortly.
The CType
function takes a value and a data type as parameters and returns the value converted into the data type. For example, the following code converts the text entered by the user in the txtCost TextBox
into a Decimal
and saves it in the variable cost
:
Dim cost As Decimal = CType(txtCost.Text, Decimal)
Like the Visual Basic conversion functions, CType
works only if the conversion is possible. For example, if the user types "eleven" in the TextBox, CType
will cause an error.
The DirectCast
operator converts an object from one type to another. For example, event handlers have a sender
parameter of type Object
that holds a reference to the control that raised the event. If you know that the control is actually a Button
, you can use DirectCast
to convert sender
into a variable of type Button
as shown in the following code:
Private Sub btnSetColor_Click() Dim btn As Button = DirectCast(sender, Button) ... End Sub
This is particularly handy when you want one event handler to catch events raised by multiple controls. After converting sender
into a Button
, the program can use the Button
's properties to decide how to proceed.
The DirectCast
operator fails if the object you are trying to convert doesn't have the correct data type. For example, if the preceding event handler were invoked by a PictureBox
, then sender
would not be a Button
so the call to DirectCast
would fail.
The TryCast
operator attempts to convert an object from one data type to another much as DirectCast
does but if there is a problem TryCast
returns Nothing
instead of throwing an exception. The following code shows the previous event handler rewritten so it doesn't crash if the sender
that raised the event isn't a Button
.
Private Sub btnSetColor_Click() Dim btn As Button = TryCast(sender, Button) If btn IsNot Nothing Then ... End If ... End Sub
This code uses TryCast
to convert sender
into a Button
. It then uses IsNot
to see if the result is Nothing
. (The IsNot
operator is described later in the section "Comparison Operators.") If the result isn't Nothing
, the code executes whatever is inside the If Then
block.
The Convert
class provides methods that convert from one data type to another. For example, the following code converts the text entered by the user in the txtCost TextBox
into a Decimal
and saves it in the variable cost
:
Dim cost As Decimal = Convert.ToDecimal(txtCost.Text)
A method is simply a function or subroutine provided by a class as opposed to in a separate code module. In this case, the Convert class provides these methods.
Table 11-3 lists the Convert
class's conversion methods.
Table 11.3. TABLE 11-3
METHOD | CONVERTS TO |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
| 16-bit integer ( |
| 32-bit integer ( |
| 64-bit integer ( |
|
|
|
|
|
|
| Unsigned 16-bit integer ( |
| Unsigned 32-bit integer ( |
| Unsigned 64-bit integer ( |
One drawback to the Convert
methods is that they require you to remember how long the integer data types are in bits. For example, you need to use ToInt32
to convert to a 32-bit Integer
.
Trying to find structure and meaning in text is called parsing. All the simple data types (Integer, Double, Decimal
) provide a Parse
method that converts text into that data type. For example, the Integer
data type's Parse
method takes a string as a parameter and returns an Integer
; at least it does if the string contains an integer value.
For example, the following code parses the text entered by the user in the txtCost TextBox
to get a Decimal
value and saves it in the variable cost
:
Dim cost As Decimal = Decimal.Parse(txtCost.Text)
Like the previous methods, this works only if the text can reasonably be converted into a decimal
. If the user types "12,345.67," the parsing works. If the user types "ten" or "1.2.3," the parsing fails.
Unfortunately, Visual Basic's conversion and parsing methods are confused by some formats that you might expect them to understand. For example, they can't handle currency characters, so they fail on strings like "$12.34" and "€54.32."
You can tell the Decimal
class's Parse
method to allow currency values by passing it a second parameter as shown in the following code:
Dim cost As Decimal = Decimal.Parse(txtCost.Text, System.Globalization.NumberStyles.Any)
All the parsing methods described so far have one really big problem: if the value they are converting cannot be converted into the desired data type, they cause an error that crashes your program (at least until you read Lesson 21 on handling errors).
One way to avoid this problem is to use TryParse
. A data type's TryParse
method is a lot like Parse
except it returns a Boolean value indicating whether it succeeded. It takes a second parameter to hold the parsed value.
For example, consider the following code:
Dim cost As Decimal If Decimal.TryParse(txtCost.Text, cost) Then ' Perform some calculations... Else MessageBox.Show("Please enter a valid cost.") End If
The first statement calls TryParse
, passing it the value to convert (txtCost.Text
) and the variable (cost
) that should receive the Decimal
value. TryParse
attempts to convert the user's text into a Decimal
and returns True
if it succeeds. The code then uses an If Then Else
statement to either process the value or display an error message.
Like Parse, TryParse
doesn't automatically understand text with a currency format. To make it allow currency formats, you can add extra parameters as shown in the following code:
Dim cost As Decimal If Decimal.TryParse(txtCost.Text, System.Globalization.NumberStyles.Any, Nothing, cost) Then MessageBox.Show("OK") Else MessageBox.Show("Failed") End If
This syntax is the most cumbersome of the conversion methods described here, but it is also the most robust.
Which of these methods you use to convert between data types is largely a matter of preference. Many developers prefer the Visual Basic conversion functions such as CInt
and CDec
because they're short and easy to read (once you get used to them). Others prefer CType
.
For parsing user-entered values, however, you should generally use TryParse
so you can easily detect errors (although I often use Parse
in examples because it's easier to read, even if it isn't as robust).
You've already seen several pieces of code that assign a value to a variable. For example, the following code converts the text in the txtSalary TextBox
into a Decimal
and saves it in the variable salary
:
Dim salary As Decimal = Decimal.Parse(txtSalary.Text)
You can also save a value that is the result of a more complex calculation into a variable on the left side of an equals sign. Fortunately, the syntax for these kinds of calculations is usually easy to understand. The following code calculates the value 2736 + 7281 / 3 and saves the result in the variable named result
:
Dim result As Double = 2736 + 7281 / 3
The operands (the values used in the expression) can be literal values, values stored in variables, or the results of methods. For example, the following code calculates the sales tax on a purchase's subtotal. It multiplies the tax rate stored in the taxRate
variable by the Decimal
value stored in the txtSubtotal TextBox
and saves the result in the variable salesTax
:
salesTax = taxRate * Decimal.Parse(txtSubtotal.Text)
Note that a variable can appear on both sides of the equals sign. In that case, the value on the right is the variable's current value; and after the calculation, the new result is saved back in the same variable.
For example, the following code takes x
's current value, doubles it, adds 10
, and saves the result back in variable x
. If x
started with the value 3
, then when this statement finishes, x
holds the value 16
.
x = 2 * x + 10
A variable may appear more than once on the right side of the equals sign but it can appear only once on the left.
The following sections provide some additional details about performing calculations.
If an expression uses two different data types, Visual Basic promotes the one with the narrower data type. For example, if you try to divide an Integer
by a Single
, Visual Basic promotes the Integer
to a Single
before it performs the division.
Visual Basic also performs this promotion if the operation would lead to a wider data type. For example, if you divide two integers, the result might not be an integer. To allow for fractional results, Visual Basic promotes the values to Doubles
before performing the division. The result is a Double
so you need to treat it as one. For example, the following code is not allowed (if you have Option Strict turned on) because you cannot save a Double
result in an Integer
:
Dim result As Integer = 8 / 4
Visual Basic has many operators for manipulating variables of different data types. The following sections describe the most commonly used operators grouped by operand type (arithmetic, string, logical, and so forth).
The arithmetic operators perform calculations on numbers. Table 11-4 summarizes these operators. The Example column shows sample results.
Table 11.4. TABLE 11-4
OPERATOR | MEANING | EXAMPLE |
---|---|---|
| Exponentiation |
|
| Addition |
|
| Negation |
|
| Subtraction |
|
| Multiplication |
|
Division (integer) |
| |
| Division (floating point) |
|
| Modulus |
|
Integer division drops any remainder and returns the integer quotient. The modulus operator does the opposite: It drops the quotient and returns the remainder. For example, 17 Mod 5
returns 2
because 17
divided by 5
is 3
with a remainder of 2
.
The logical operators perform calculations on Boolean (True
or False
) values. They let you combine logical statements to form new ones.
Lesson 18 explains how to use these values to perform tests that let a program take action only under certain circumstances. For example, a program might pay an employee overtime if the employee is paid hourly and works more than 40 hours in a week.
Table 11-5 summarizes these operators.
Table 11.5. TABLE 11-5
OPERATOR | RETURNS TRUE WHEN... |
---|---|
| Both operands are |
| Both operands are |
| One or both operands is |
| One or both operands is |
| One operand is |
| The single operand is |
The exclusive or operator Xor
is perhaps the most confusing. It returns True
if one of its operands is True
and the other is False
. For example, you and Ann will get a single lunch check and pay each other back later if either Ann forgot her money and you brought yours, or Ann remembered her money and you forgot yours. If neither of you forgot your money, you can get separate checks. If you both forgot your money, you're both going hungry today.
singleCheck = annForgotMoney Xor youForgotMoney;
AndAlso
and OrElse
are called conditional operators or short-circuit operators. They work just like the regular And
and Or
operators except they don't evaluate their second operand unless necessary. For example, consider the following AndAlso
statement:
mustBuyLunch = isLunchTime AndAlso forgotToBringLunch
Suppose it's only 9:00 a.m., so isLunchTime
is false. When the program sees this expression, evaluates isLunchTime
, and sees the AndAlso
operator, it already knows that mustBuyLunch
must be false no matter what value follows the AndAlso
(in this case forgotToBringLunch
), so it doesn't bother to evaluate forgotToBringLunch
, which saves a tiny amount of calculation time.
Similarly, consider the following "or" statement:
canAffordLunch = haveEnoughMoney OrElse haveCreditCard
If you have enough money, haveEnoughMoney
is True
, so the program doesn't need to evaluate haveCreditCard
to know that the result canAffordLunch
is also True
.
Because the conditional AndAlso
and OrElse
operators are slightly faster, most developers use them when they can instead of And
and Or
.
There is one case where the conditional operators may cause problems. If the second operand is not a simple value but the returned result from some sort of subroutine call, then if you use a conditional operator, you cannot always know whether the subroutine was called. This might matter if the subroutine has side effects, consequences that last after the subroutine has finished, such as opening a database or creating a file. In that case, you cannot know later whether the database is open or the file is created, so the code might not work properly.
This is seldom a problem, and you can avoid it completely by avoiding side effects.
The only string operator Visual Basic provides is &. This operator concatenates (joins) two strings together. For example, suppose the variable username
contains the user's name. The following code concatenates the text "Hello " (note the trailing space) with the user's name and displays the result in a message box:
MessageBox.Show("Hello " & username)
Actually the + operator will also concatenate strings but it can make the code hard to read and the results aren't always obvious, for example, if you use + to combine an Integer
and a String
. Concatenating strings with + is a bad practice.
Lesson 14 explains methods that you can use to manipulate strings: find substrings, replace text, check length, and so forth.
One very non-obvious fact about string operations is that a string concatenation does not really save the results in the same memory used by the variable on the left side of an assignment statement. Instead, it creates a new string holding the result of the calculation and makes the variable refer to that.
For example, consider the following code:
String greeting = txtUserName.Text greeting = "Hello" + username
This code looks like it saves a user's name in the variable username
and then tacks "Hello " onto the front. Actually, the second statement creates an entirely new string that holds "Hello " plus the user's name and then makes greeting
refer to the new string.
For most practical applications, the difference is small, and you can ignore it. However, if you're performing many concatenations (perhaps in one of the loops described in Lesson 19), then your program may have performance issues. The StringBuilder
class can help address this issue, but it's a bit more advanced so I'm not going to cover it here. See msdn.microsoft.com/library/2839d5h5.aspx
for more information.
The comparison operators compare two values and return True
or False
depending on the values' relationship. For example, x < y
returns True
if x
is less than y
.
Table 11-6 summarizes these operators.
Table 11.6. TABLE 11-6
OPERATOR | MEANING | EXAMPLE |
---|---|---|
| Equals |
|
| Not equals |
|
| Less than |
|
| Less than or equal to |
|
| Greater than |
|
| Greater than or equal to |
|
| Returns |
|
| Returns |
|
The Is
and IsNot
operators are a bit unusual because they work only on reference variables that refer to objects not on more ordinary data types such as Integers
and Doubles
.
These operators compare variables to see if they refer to the same object. They don't compare the values in two different objects. For example, suppose you have two Person
objects, person1
and person2
, that happen to have the same FirstName, LastName
, and other property values. Even if their properties are identical, they are two distinct objects so person1 Is person2
would return False
.
The assignment operators set a variable (or property or whatever) equal to something else. The simplest of these is the =
operator, which you have seen several times before. This operator simply assigns whatever value is on the right to the variable on the left.
The other assignment operators, known as compound assignment operators, combine the variable's current value in some way with whatever is on the right. For example, the following code adds 3
to whatever value x
currently holds:
x += 3
This has the same effect as the following statement that doesn't use the +=
operator:
x = x + 3
Table 11-7 summarizes these operators.
Table 11.7. TABLE 11-7
OPERATOR | MEANING | EXAMPLE | MEANS |
---|---|---|---|
| Assign |
| x = 10 |
| Add and assign |
| x = x + 10 |
| Subtract and assign |
| x = x - 10 |
| Multiply and assign |
| x = x * 10 |
| Integer-point divide and assign |
| x = x 10 |
| Floating-point divide and assign |
| x = x / 10 |
| Concatenate and assign |
| x = x & ″A″ |
There are no compound assignment operators for Mod
or the logical operators.
The bitwise operators enable you to manipulate the individual bits in integer values. For example, the bitwise Or
operator combines the bits in two values, so the result has a bit equal to 1 wherever either of the two operands has a bit equal to one.
For example, suppose x
and y
are the byte values, with bits 10000000 and 00000001. Then x Or y
has bits 10000001.
These are fairly advanced operators so I'm not going to do much with them, but Table 11-8 summarizes them. The shift operators are not "bitwise" because they don't compare two operands one bit at a time, but they are bit-manipulation operators so they're included here.
Table 11.8. TABLE 11-8
OPERATOR | MEANING | EXAMPLE |
---|---|---|
| Bitwise and |
|
| Bitwise or |
|
| Bitwise xor |
|
| Bitwise complement |
|
| Left shift |
|
| Right shift (for signed types) |
|
| Right shift (for unsigned types) |
|
If the operand has a signed type (SByte, Integer, Long
), then >>
makes new bits on the left copies of the value's sign bit (its leftmost bit). If the operand has an unsigned type (Byte, UInteger, ULong
), then >>
makes new bits 0.
The shift operators also have corresponding compound assignments operators <<=
and >>=
.
Sometimes the order in which you evaluate the operators in an expression changes the result. For example, consider the expression 2 + 3 * 5
. If you evaluate the +
first, you get 5 * 5
, which is 25
; but if you evaluate the *
first, you get 2 + 15
, which is 17
.
To prevent any ambiguity, Visual Basic defines operator precedence to determine which operation is evaluated first.
Table 11-9 lists the operators in order of decreasing precedence. In other words, the operators listed at the beginning of the table are applied before those listed later. Operators listed at the same level have the same precedence and are applied left to right in the order in which they appear in the expression.
Table 11.9. TABLE 11-9
CATEGORY | OPERATORS |
---|---|
Exponentiation |
|
Unary |
|
Multiplication and floating-point division |
|
Integer division | |
Modulus |
|
Addition, subtraction, concatenation |
|
Bit shift |
|
Comparison |
|
Logical negation |
|
Logical |
|
Logical |
|
Logical |
|
The compound assignment operators (+=, *=, ^=
, and so forth) always have lowest precedence. The program evaluates the expression on the right, combines it with the original value of the variable on the left, and then saves the result in that variable.
By carefully using the precedence rules, you can always figure out how a program will evaluate an expression, but sometimes the expression can be confusing enough to make figuring out the result difficult. Trying to determine precedence in confusing expressions can be a great party game (the programmer's version of "Pictionary"), but it can make understanding and debugging programs hard.
Fortunately, you can always use parentheses to change the order of evaluation, or to make the default order obvious. For example, consider the following three statements:
x = 2 + 3 * 5 y = 2 + (3 * 5) z = (2 + 3) * 5
The first statement uses no parentheses so you need to use the precedence table to figure out which operator is applied first. The table shows that *
has higher precedence than +
, so *
is applied first and the result is 2 + 15
, which is 17
.
The second statement uses parentheses to emphasize the fact that the *
operator is evaluated first. The result is unchanged but the code is easier to read.
The third statement uses parentheses to change the order of evaluation. In this case the +
operator is evaluated first, so the result is 5 * 5
, which is 25
.
Parentheses are useful tools for making your code easier to understand and debug. Unless an expression is so simple that it's obvious how it is evaluated, add parentheses to make the result clear.
A constant is a lot like a variable except you must assign it a value when you declare it and you cannot change the value later.
Syntactically, a constant's declaration is similar to a variable except it uses the keyword Const
instead of Dim
.
For example, the following code declares a Decimal
constant named taxRate
and assigns it the value 0.09D
. It then uses the constant in a calculation.
Const taxRate As Decimal = 0.09D Dim subtotal As Decimal = Decimal.Parse(txtSubtotal.Text) Dim salesTax As Decimal = taxRate * subtotal Dim grandTotal As Decimal = subtotal + salesTax
The D
character in the code tells Visual Basic that 0.09
is a Decimal
value. Without this character, Visual Basic thinks 0.09
is a Double
and complains when you try to assign it to a Decimal
constant.
Constants work just like literal values so you could replace the constant taxRate
with the literal value 0.09D
in the preceding calculation. Using a constant makes the code easier to read, however. When you see the value 0.09D
, you need to remember or guess that this is a tax rate. In contrast, the meaning of the constant taxRate
is obvious.
Not only can it be hard to remember what this kind of "magic number" means, but it can also make changing the value difficult if it appears in many places throughout the program. Suppose the code uses the value 0.09D
in several places. If the tax rate goes up, you need to hunt down all of the occurrences of that number and change them. If you miss some of them, you could get very confusing results.
Note that constants can contain calculated values as long as Visual Basic can perform the calculation before the program actually runs. For example, the following code declares a constant that defines the number of centimeters per inch. It then uses that value to define the number of centimeters per foot.
Const cmPerInch As Double = 2.54 Const cmPerFoot As Double = cmPerInch * 12
In this Try It you perform some simple calculations. You take values entered by the user, convert them into numbers, do some multiplication and addition, and display the results.
You can download the code and resources for this Try It from the book's web page at www.wrox.com
or www.vb-helper.com/24hourvb.html
. You can find them in the Lesson11 folder in the download.
In this lesson:
Create the form shown in Figure 11-1.
Make the program do the following when the user clicks the Calculate Button
:
Multiply each item's Quantity value by its Price Each value and display the result in the corresponding Ext. Price textbox.
Add up the Ext. Price values and display the result in the Subtotal textbox.
Multiply the Subtotal by the Tax Rate and display the result in the Sales Tax textbox.
Add the Subtotal, Sales Tax, and Shipping values and display the result in the Grand Total textbox.
It is often helpful to perform this kind of calculation in three separate phases:
Gather input values from the user and store them in variables.
Perform calculations.
Display results.
Use the Decimal
data type for all the variables because they represent currency.
Lesson 14 has more to say about manipulating and formatting strings, but for this Try It it's helpful to know that all data types provide a ToString
method that converts a value into a string. An optional parameter string indicates the format to use. For this Try It, use the format "C"
(including the quotes) to indicate a currency format, as in:
txtGrandTotal.Text = grandTotal.ToString("C")
Create the form shown in Figure 11-1.
Create the controls. Use NumericUpDown
controls for the Quantity values.
Set ReadOnly
to True
for the TextBoxes
that display results (Subtotal, Sales Tax, and Grand Total).
Make the program do the following when the user clicks the Calculate button:
Multiply each item's Quantity value by its Price Each value and display the result in the corresponding Ext. Price textbox.
Add the Ext. Price values and display the result in the Subtotal textbox.
Multiply the Subtotal value by the entered Tax Rate and display the result in the Sales Tax textbox.
Add the Subtotal, Sales Tax, and Shipping values and display the result in the Grand Total textbox.
This is easy to do in three steps:
Gather input values from the user and store them in variables. Because they are already numeric, the code doesn't need to parse the values that come from the NumericUpDown
control's Value
properties. The program does need to parse the values in TextBox
es to convert them into Decimal
values. The following code snippet shows how the program can read the Quantity and Price Each values for the first item. Read the other values similarly.
' Get input values. Dim quantity1 As Decimal = nudQuantity1.Value ... Dim priceEach1 As Decimal = Decimal.Parse(txtPriceEach1.Text) ...
Perform calculations. In this Try It, the calculations are pretty simple. Notice that the code uses a separate variable for each result, instead of trying to add them all at once, to keep the code simple and easy to read:
' Calculate results. Dim extPrice1 As Decimal = quantity1 * priceEach1 Dim extPrice2 As Decimal = quantity2 * priceEach2 Dim extPrice3 As Decimal = quantity3 * priceEach3 Dim extPrice4 As Decimal = quantity4 * priceEach4 Dim subtotal As Decimal = extPrice1 + extPrice2 + extPrice3 + extPrice4 Dim salesTax As Decimal = subtotal * taxRate Dim grandTotal As Decimal = subtotal + salesTax + shipping
Display results. The program uses "C"
to display values in a currency format:
' Display results. txtExtPrice1.Text = extPrice1.ToString("C") txtExtPrice2.Text = extPrice2.ToString("C") txtExtPrice3.Text = extPrice3.ToString("C") txtExtPrice4.Text = extPrice4.ToString("C") txtSubtotal.Text = subtotal.ToString("C") txtSalesTax.Text = salesTax.ToString("C") txtGrandTotal.Text = grandTotal.ToString("C")
Please select Lesson 11 on the DVD to view the video that accompanies this lesson.
Make a program similar to the one shown in Figure 11-2. When the user checks or unchecks either of the A or B CheckBoxes
, the program should check or uncheck the result CheckBoxes
appropriately. For example, if A and B are both checked, the A and B CheckBox
should also be checked.
The last CheckBox
is checked at the same time as one of the others. Which one? Does that make sense?
There are many ways for a program to get information about the operating system. The following lists three useful values:
Environment.UserName
— The current user's name
DateTime.Now.ToShortTimeString()
— The current time in short format
DateTime.Now.ToShortDateString()
— The current date in short format
Make a program that greets the user when it starts by displaying a message box similar to the one shown in Figure 11-3. (Hint: You'll need to concatenate several strings together.)
Make a program to determine whether 12345 * 54321 > 22222 * 33333. In three Labels
, display the result of 12345 * 54321, the result of 22222 * 33333, and the Boolean value 12345 * 54321 > 22222 * 33333. The final value should be true or false. (Hint: Use ToString
to convert the Boolean result into a string.)
Make a program that converts degrees Celsius to degrees Fahrenheit. It should have two TextBox
es with associated Button
s. When the user enters a value in the Celsius TextBox
and clicks its Button
, the program converts the value into degrees Fahrenheit and displays the result in the other TextBox
. Make the other Button
convert from Fahrenheit to Celsius. (Hint: °F = °C * 9 / 5 + 32 and °C = (°F – 32) * 5 / 9.) (What's special about the temperature −40° Celsius?)
Make a money converter that converts between U.S. dollars, British pounds, euros, Japanese yen, Indian rupees, and Swiss francs. Make constants for the following conversion factors (or go online and look up the current exchange rates):
' Exchange rates in USD. Const eurPerUsd As Decimal = 0.79D Const gbpPerUsd As Decimal = 0.64D Const jpyPerUsd As Decimal = 84.64D Const inrPerUsd As Decimal = 46.82D Const chfPerUsd As Decimal = 1.03D
To make the constants usable by every event handler in the program, place these declarations outside of any event handler.
Make a TextBox
and Button
for each currency. When the user clicks the Button
, the program should:
Get the value in the corresponding TextBox
.
Convert that value into U.S. dollars.
Use the converted value in U.S. dollars to calculate the other currency values.
Display the results. (Note that these event handlers contain a lot of duplicated code, which is not good programming practice. Lesson 20 explains how you can make a subroutine to perform the duplicated work for the event handlers.)
Make a program similar to the one you made for Exercise 5 but make this one convert between inches, feet, yards, miles, centimeters, meters, and kilometers.
You can find solutions to this lesson's exercises in the Lesson11 folder inside the download available on the book's web site at www.wrox.com
or www.vb-helper.com/24hourvb.html
.