|
Chapter 4: Using Operators and Expressions
Chapter 4 Using Operators and ExpressionsThis chapter introduces two of the unsung heroes of nearly every computer language: operators and expressions. Contrary to some reports, operators aren't people who control mechanical equipment. Instead, they're special symbols or words that specify an operation or an action that you want to occur between two or more values. Addition signs and subtraction signs are some of the most common operators, but there are many more. This chapter will get you up to speed. Expressions, likewise, aren't something you practice in the mirror before a date or a job interview. In programming languages such as Microsoft Visual Basic .NET, they're combinations of operators and values that the computer can evaluate. For example, 1 + 1 is a simple expression.Operators and expressions are hardly the glamour features of any programming language. They've been around so long that differences in the way they work from one language to another are usually minor. The reason for this ubiquity, of course, is utility. No programmer could get along without operators and expressions and so, most likely, neither can you. Are you ready?
Introducing OperatorsIn computer programming, an operator is a symbol that tells the computer to perform a specific type of processing. The plus sign, for example, is an operator that tells the computer to add the number that precedes it and the number that follows it. Here's an example.
intSum = intChickens + intCows The variables intChickens and intCows are operands. This is because the plus sign operates on the intChickens variable and the intCows variable. The plus sign is a binary operator because it operates on two operands. Unary operators, by contrast, work on just one operand. The minus sign in the code shown here is a unary operand:
sngLowTemp = - 20.0 Both of these statements, by the way, also use the assignment operatorthe equal sign. The assignment operator evaluates the expression at its right and assigns the result to the variable at its left. In fact, Visual Basic .NET provides six kinds of operators: arithmetic, assignment, comparison, concatenation, logical, and miscellaneous. The following sections explain each kind.
Forming ExpressionsTaken together, an operator and its operands form an expression. The following, for example, is an expression:
intWins + intLosses Evaluating an expression always returns a result. The data type of that result depends on both the operator and the data types of the operands. The preceding expression, for example, returns an Integer value because each of its operands is an Integer.
It's perfectly fine to use the result of one expression as the operand of another. Here's an example that does this:
curBalance + curInterest + curPurchases - curPayments The first plus sign adds the first two operands, then the second plus sign adds that result and curPurchases, and finally the minus sign subtracts curPayments. Each of the three operators produces a Currency result because all the arguments are Currency. The next example joins three strings together; that is, it concatenates them. The ampersand (&) is the concatenation operator and it always returns a string, no matter what data types its operands might be. In this example, the first ampersand concatenates strFirstName and a space; the second concatenates that result and the variable strLastName:
strFirstName & " " & strLastName When an expression contains multiple operators, Visual Basic .NET evaluates them in order using these rules:
10 - 4 - 3 equals 3 because Visual Basic .NET first subtracts 4 from 10, and then subtracts 3 from 6. If this isn't what you want, you can code
10 -(4 - 3) Visual Basic .NET doesn't process the operators in this expression in strict left-to-right order as it did in the previous expression. Instead, it starts with the operator inside the parentheses. To be precise, it first subtracts 3 from 4, and only then subtracts the resulting 1 from 10.
10 + 4 * 3 Did you guess 22? According to Table 4-1, the multiplication operator (*) has precedence over the addition operator (+). Therefore, Visual Basic .NET performs the multiplication first, as if you'd coded:
10 + (4 * 3) If the list of operators in Table 4-1 seems confusing, take heart. The rest of this chapter explains them.
Table 4-1 Operator Precedence in Visual Basic .NET
In fact, most programmers neither try nor succeed at memorizing these operator rules. It's much more accurate to code what you want by using parentheses. For proof, compute the value of this expression:
5 + -3 * 4 ^ 3 Not so easy, right? Did you get -187? Now try this one, whichas far as Visual Basic .NET is concernedis perfectly equivalent to the previous one:
5 + (-3 * (4 ^ 3)) Arithmetic operators are notorious for producing unexpected results when you code several of them in the same expression. This occurs because invariably, Visual Basic .NET doesn't process the operators in the sequence you expect. There are two choices for dealing with this issue:
Using Arithmetic OperatorsTable 4-2 lists the arithmetic operators that Visual Basic .NET supports. None of these should be surprising until you get to division, of which there are two kinds.Table 4-2 Visual Basic .NET Arithmetic Operators
The Mod operator returns the remainder from an Integer division. The expression 17 Mod 5, for example returns a value of 2 because 17 divided by 5 is 3 remainder 2. To get both the quotient and the remainder of an Integer division, you must code two distinct statements as shown here (the Dim statements are only for clarity):
Dim intDivisor As Integer = 5
The exponentiation operator raises a number to a power. The expression
Converting Numeric TypesNumeric operations involving mixed data types are permissible and generally produce the result you want. This is possible because of some details Visual Basic .NET handles behind the scenes. Specifically, Visual Basic .NET:
This, of course, begs the question of what type the result should be. Here are the rules.
If you add a Byte and a Short, the result will be a Short. If you add a Short and an Integer, the result will be an Integer. If the operands are a Long and a Decimal, the result will be a Decimal. The data type that can hold the largest number will be the data type of the result.
Using Assignment OperatorsThe assignment operator assigns a value to a variable. In Visual Basic .NET, as in most programming languages, the assignment operator is the equal sign. Here's a very simple example that uses the assignment operator. It assigns the value 42 to the variable x.
x = 42 The left operand receives the value of the right operand, and must be a single variable name or property. The first statement shown here is valid because it assigns a value to a property. The second is unacceptable because the value on the left isn't a single variable name or property.
lblTotal.Text = dblTotal The right operand can be any literal, variable, expression, or function that returns a value, as in this example:
sngTravelTime = Math.Abs(sngEnd - sngStart) / sngSpeed
Using Compound OperatorsA high percentage of assignment statements mention the same variable on both sides of the assignment operator. Here's an example.
intCount = intCount + 1 To save you some typing, Visual Basic .NET provides a special operator, +=, that combines the functions of the addition operator and the assignment operator. The following statement is equivalent to the previous one. In normal language, it reads, "Add one to intCount":
intCount += 1
Operators that combine assignment with arithmetic are available for all the arithmetic operators and also for the String concatenation operator. Visual Basic .NET calls them compound operators. Table 4-3 provides a complete list. Table 4-3 Visual Basic .NET Compound Operators
Understanding Type ConversionIn any assignment statement, the receiving variable must be capable of receiving the value you want to assign. You can't, for example, assign a String value like "Medieval History" to an Integer variable. This would produce this error message:Cast From String "Medieval History" To Type 'Integer' Is Not Valid.
If the assigned value and the receiving variable are the same type and if that's a value typeyou're home free. You can always assign an Integer value to an Integer variable, a String value to a String variable, and so forth.
If the assigned value and the receiving variable are different types, Visual Basic .NET might attempt type conversion on your behalf. Suppose, for example, that you try to store an Integer value in a Long variable. Visual Basic casts the Integer value to a Long value and then stores the Long value. Numeric type conversions can be either widening or narrowing. A widening conversion means that the data type of the receiving variable can hold a larger number than the data type of the value you're trying to store. If, for example, you assign an Integer (32-bit) value to a Long (64-bit) variable, a widening conversion takes place. Widening conversions are always acceptable. A narrowing conversion means that the data type of the receiving variable can't hold numbers as large as the data type of the value you're trying to store. Suppose, for example, you assign an Integer (32-bit) value to a Byte (8-bit) variable. Any one of three things can happen:
Option Strict On Disallows Implicit Conversions From 'Integer' To 'Byte'.
An Unhandled Exception Of Type 'System.OverflowException' Occurred. Additional Information: Arithmetic Operation Resulted In An Overflow.
In the following numeric data typesByte, Short, Integer, Long, Decimal, Single, Doubleconversions in a left-to-right direction are widening. Conversions in a right-to-left direction are narrowing.
Assigning Reference Variables The assignment operator might surprise you when you try to assign one reference variable to another. To understand why, recall that reference variables don't actually contain data. Instead, they contain a pointer to the data.
Consider, for example, the String data type. From moment to moment, the value of a String variable might be 0 bytes in length, 1 byte in length, or thousands of bytes in length. How much memory should Visual Basic .NET reserve when you declare a String? There's no way to tell! The solution to this dilemma is ingenious. Suppose that you declare a variable as follows:
Dim strMessage As String = "No problems found." The literal "No problems found." contains 18 characters, so Visual Basic .NET asks the operating system for 36 bytes of memory, stores the given value there, and stores the address of the 36 bytes in the strMessage variable. Later, however, you change the value of the strMessage variable by coding:
strMessage = "Regrettably, the hippopotamus has run amok."
The new value is 43 characters long and therefore requires 86 bytes of memory. This won't fit in the 36 bytes currently allocated, so Visual Basic .NET asks the operating system for 86 more bytes of memory, stores the new value there, stores the new address in the strMessage variable, and finally gives the original 36 bytes back to Windows.
Is this perfectly clear? String is a reference type because a String variable doesn't actually contain the String value; it contains an address that refers to the actual String value. What happens when you assign the value of one reference type to another? In the case of strings, Visual Basic .NET:
However, String is one of the few reference types that work this way. For most reference types, including arrays, the assignment operator simply copies the pointer value. Can you see the implications of this? Suppose that you declared two arrays like this:
Dim strTools() As String = {"Auger", "Blowtorch", "Chisel"}The strTools variable would point to a structure that contained various information about the arrayit's data type, its rank, and the maximum subscript in each dimension, for exampleplus an array of pointers to String values. The strFruit variable would point to a similar structure. Now, suppose that you code this statement:
strTools = strFruit
When this statement executes, it copies the pointer in the strFruit variable into the strTools variable. This means that the strTools variable will point to exactly the same memory location as the strFruit variable. strTools(0) and
strTools(0) = "Drill" Would you expect strFruit to equal Drill as well? Well, it does. Any change you make using the strTools variable will show up when you access the array using the strFruit variable (and vice versa). This is because strTools and strFruit both point to the same array.
The point of all this is to be very careful when using the assignment operator with other than elementary data types. Having two variables point to the same object in memory is sometimes useful, but other times it's definitely not what you want. Incidentally, the following statements will truly copy the strFruit array to the strTools array:
Dim intPos As Integer
Here are the salient points regarding this code:
Note that because this statement is assigning String values and not entire arrays, it copies the value and not the reference.
Most data types have built-in methods that carry out common operations. These vary depending on the data type, but one-dimensional arrays have a method for copying themselves. Here's an example.
strFruit.CopyTo(strTools, 0)
This statement copies all the elements of the strFruit array into the strTools array, starting at position zero of the strTools array. To search for methods that operate on a given data type, follow these steps:
Using Comparison OperatorsVisual Basic .NET supports the comparison operators listed in Table 4-4. If both operands are numeric, Visual Basic .NET compares them numerically. If one or both are characters or strings, Visual Basic .NET compares them as text.Table 4-4 Visual Basic .NET Comparison Operators
Comparing NumbersThe rules for comparing two numbers are essentially the same as those for performing arithmetic on them. If the numbers have different data types, Visual Basic .NET temporarily converts the narrower type to the wider one.If you compare two numbers, Visual Basic .NET compares them numerically. That's no surprise. If, however, you compare a numeric data type to a string, Visual Basic .NET converts the number to a string and then performs a string comparison, explained in the next section.
Comparing StringsWhen comparing two strings, Visual Basic .NET starts by comparing the first character of each operand, then the next character of each operand, and so forth, until it finds two unequal characters or until one string runs out of characters.
Text comparisons can be either case-sensitive or non-case-sensitive, depending on the current Option Compare setting, as follows:
A 0041 B 0042 a 0061 b 0062 With Option Compare Binary in effect, the letters A and a wouldn't be equal because 0041 doesn't equal 0061. Furthermore, B would come before a because 0042 is less than 0061.
Option Compare Binary is the default. To override this, add the following line at the top of the file that contains your code:
Option Compare Text Be aware, however, that this setting affects every String value comparison in the file that contains it. As a result, most programmers allow Option Compare Binary to remain in effect. If they need to perform a case- insensitive comparison, they temporarily convert both strings to the same case. Here are two examples. (UCase is a Visual Basic .NET built-in function that converts a string to uppercase. Similarly LCase is a built-in function that converts String values to lowercase.)
Dim strItem1 As String = "fishLINE"
Using the Like OperatorThe Like operator compares a String to a pattern. If the two match, the comparison is True; otherwise, of course, it's False. If both the String and the pattern are empty, the result is True. If only one is empty, the result is False. Table 4-5 lists the available patterns.Table 4-5 Patterns for Comparisons Using the Like Operator
Using the Like operator requires knowing its quirks and peculiarities. Here are some tips:
"abc" Like "a[xyzb]c" is true because a matches a, b matches one of the characters in xyzb, and c matches c.
"aaXaa" Like "aa*aa"
"A" Like "[0-9A-F]"
"-A" Like "[-02468][A-Z]"
"void" Like "[!a-u]oid"
Getting It Together with Concatenation OperatorsYou can concatenate strings using either the plus (+) operator or the ampersand (&) operator. The following statements are equivalent:
strResult = "Welcome to " + "my circus." Experienced programmers, however, never use the plus (+) operator for joining strings. There are two very good reasons for this:
In the end it comes down to this: Use the concatenation operator (&) for concatenating and the addition operator (+) for adding. What could be easier than that? When you concatenate (that is, join) Strings, you must always include spaces around the & operator. If you try to code an expression such as a&b&c, the compiler will report a syntax error and halt. You must instead code a & b & c.
Using Logical OperatorsLogical operators work strictly with Boolean (that is, True/False) operands. The And operator, for example, is useful for determining if two True/ False conditions are both True. Table 4-6 lists the complete set of logical operators that Visual Basic .NET provides.Table 4-6 Visual Basic .NET Logical Operators
With the exception of Not, all of these operators require two operands as shown here. Note that each operand is an expression that evaluates to True or False.
(lngOrderQty > 0) And (lngOnHandQty > 0) If you supply a numeric argument where Visual Basic .NET expects a Boolean argument, Visual Basic .NET converts the argument for you. A zero value is False and all nonzero values are True. The following If statements are equivalent:
If lngOrderQty <> 0 Then
Using Short-Circuited OperatorsTo understand the difference between And and AndAlso, consider the following expression:
IsNumeric(strQty) And (CLng(strQty) > 0) IsNumeric is a built-in function that returns True if the value you supply is a number, or if Visual Basic .NET can convert it to one. CLng is a built-in function that converts a value to a Long. Here, then, is how Visual Basic evaluates the expression:
Do you see the problem here? If strQty contains a nonnumeric value such as "xyz", executing the expression CLng(strQty) will throw an exception because there's no way of converting a string like xyz to a number. One way
If IsNumeric(strQty) Then But the new AndAlso operator provides a more elegant solution:
If IsNumeric(strQty) AndAlso (clng(strQty) > 0) Then This tells Visual Basic .NET that if IsNumeric(strQty) turns out to be False, it shouldn't bother evaluating (CLng(strQty) > 0). After all, if the first operand of an And expression is False, the entire expression will be False, no matter the state of the second operand. Therefore, Visual Basic .NET skips (short-circuits) evaluating the second operand. Similarly, the OrElse operator short-circuits the second operand if the first operand is True. If the first operand of an Or expression is True, the entire expression will be True no matter the state of the second operand.
Using Bitwise OperatorsThe Not, And, Or, and Xor operators have a second use: they can manipulate the individual bits of integer values. An integer value, in this case, means a value of type Byte, Short, Integer, or Long.When you apply the Not operator to an integer value, it changes all the 0 bits to 1 and all the 1 bits to 0. Consider, for example, the following variable:
Dim srtStack As Short = 1 In binary, this variable would contain the bits 0000 0000 0000 0001. Executing the following statement would transform this value to 1111 1111 1111 1110 which, on an Intel processor, is equal to -2:
srtStack = Not srtStack And, Or, and Xor perform bitwise arithmetic when you code them with integral operands. This applies the operator to the first bit of each operand, then to the second bit of each operand, and so forth. In the following code, the Or operator sets each bit in the result to 1 if the corresponding bit in either argument is 1:
Dim intBits As Integer = 3 ' 0000 0000 0000 0011 The fact that Not, And, Or, and Xor are logical operators in some situations and bitwise operators in others can be confusing, especially if you get in the habit of coding numeric values where Visual Basic .NET expects Boolean ones. An expression like
(intBits <> 0) Or (intBats <> 0) always returns True or False. The following expression, however, can return millions of different values:
intBits Or intBats
Using Miscellaneous OperatorsThe AddressOf operator returns the address of a subroutine or function. This is useful in certain situations where you must supply the address of a procedure that Visual Basic .NET calls when a specific event occurs.The GetType operator returns the type object of the specified type. The expression GetType(Integer), for example, returns the base object that defines the entire Integer class. This can be useful for obtaining information about the type, such as its properties, methods, and events.
Testing Operators and ExpressionsReading about operators and expressions might be great fun, but the real excitement comes from coding and testing them. The purpose of this exercise, therefore, isn't to mimic a small fraction of a real program's capabilities. Instead, the purpose is to show you how to run experiments and test your work. Are you ready? Follow these steps:
Figure 4-1 Any code you enter between the Private Sub btnTest_Click statement and the End Sub statements will run whenever you click Test.
MsgBox()
Dim intStart As Integer = 125
There Were Build Errors. Continue? this means that the Visual Basic .NET compiler has detected an error in your program. Click No, locate the Task List window, and resolve each message you find there. Double-clicking any message highlights the word or statement that caused the error.
An unhandled exception of type. Visual Studio also displays Break, Continue, Ignore, and Help buttons. Click Break. Contrary to what you might think, the Break button doesn't smash, crash, destroy, or otherwise abuse your program. Instead, it breaks into the normal flow of execution and freezes your program in its tracks.
Dim intStart As Integer = 125 If Visual Studio won't let you update this code, it's because your program is still running. Click your form's close box (the X in the top-right corner) and then try changing the code again.
An Unhandled Exception Of Type 'System.InvalidCastException' Occurred In microsoft.visualbasic.dll Additional Information: Cast From String 'None' To Type 'Double' Is Not Valid.
Figure 4-2 The highlighted statement caused an exception. The Command window can display the value of any variable or exception.
Being able to inspect and diagnose a program that throws an exception is a valuable capability, but wouldn't it be great if you could break into a program anywhere you wanted and look around even if it isn't throwing exceptions? Well, you can. Just select the statement where you'd like execution to stop and then press F9. Visual Studio .NET highlights the statement in dark red and halts the program whenever that statement is about to run. Visual Studio .NET calls this inserting a breakpoint. You can also do it by right-clicking the line of code and choosing Insert Breakpoint from the shortcut menu. To remove a breakpoint, either select the line and press F9 or right- click it and choose Remove Breakpoint from the shortcut menu. To clear all breakpoints in a program, choose Clear All Breakpoints from the Debug menu. Visual Studio offers many additional debugging and diagnostic tools. You can explore these as your proficiency grows, but the information in this exercise should at least get you started. Key Points
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||