Chapter 16. Operators

An operator is a basic code element that performs some operation on one or more values to create a result. The values the operator acts upon are called operands. For example, in the following statement, the operator is + (addition), the operands are B and C, and the result is assigned to the variable A:

A = B + C

The Visual Basic operators fall into five categories: arithmetic, concatenation, comparison, logical, and bitwise. This chapter first explains these categories and the operators they contain, and then discusses other operator issues such as precedence, assignment operators, and operator overloading. Also included are discussions of some specialized issues that arise when you work with strings and dates.

ARITHMETIC OPERATORS

The following table lists the arithmetic operators provided by Visual Basic. Most programmers should be very familiar with most of them. The four operators that may need a little extra explanation are , Mod, <<, and >>.

OPERATOR

PURPOSE

EXAMPLE

RESULT

^

Exponentiation

2 ^ 3

(2 to the power 3) = 2 * 2 * 2 = 8

-

Negation

−2

−2

*

Multiplication

2 * 3

6

/

Division

3 / 2

1.5

Integer division

17 5

3

Mod

Modulus

17 Mod 5

2

+

Addition

2 + 3

5

2

Subtraction

3 - 2

1

<<

Bit left shift

10110111 >> 1

01101110

>>

Bit right shift

10110111 >> 1

01011011

The operator performs integer division. It returns the result of dividing its first operand by the second, dropping any remainder. It's important to understand that the result is truncated toward zero, not rounded. For example, 7 4 = 1 and −7 4 = −1 rather than 2 and −2 as you might expect.

The Mod operator returns the remainder after dividing its first operand by its second. For example, 17 Mod 5 = 2 because 17 = 3 * 5 + 2.

The << operator shifts the bits of an Integer value to the left, padding the empty bits on the right with zeros. For example, the byte value with bits 10110111 shifted 1 bit to the left gives 01101110. Shifting 10110111 2 bits to the left gives 11011100.

The >> operator shifts the bits of a value to the right, padding the empty bits on the left with zeros. For example, the byte value with bits 10110111 shifted 1 bit to the right gives 01011011. Shifting 10110111 2 bits to the right gives 00101101.

Unfortunately, Visual Basic doesn't work easily with bit values, so you cannot use a binary value such as 10110111 in your code. Instead, you must write this value as the hexadecimal value &HB7 or the decimal value 183. The last two entries in the table show the values in binary, so it is easier to understand how the shifts work.

CONCATENATION OPERATORS

Visual Basic provides two concatenation operators: + and &. Both join two strings together. Because the + symbol also represents an arithmetic operator, your code will be easier to read if you use the & symbol for concatenation. Using & can also make your code faster and lead to fewer problems because it lets Visual Basic know that the operands are strings.

COMPARISON OPERATORS

Comparison operators compare one value to another and return a Boolean value (True or False), depending on the result. The following table lists the comparison operators provided by Visual Basic. The first six (=, <>, <, <=, >, and >=) are relatively straightforward. Note that the Not operator is not a comparison operator, so it is not listed here. It is described in the next section, "Logical Operators."

OPERATOR

PURPOSE

EXAMPLE

RESULT

=

Equals

A = B

True if A equals B

<>

Not equals

A <> B

True if A does not equal B

<

Less than

A < B

True if A is less than B

<=

Less than or equal to

A <= B

True if A is less than or equal to B

>

Greater than

A > B

True if A is greater than B

>=

Greater than or equal to

A >= B

True if A is greater than or equal to B

Is

Equality of two objects

emp Is mgr

True if emp and mgr refer to the same object

IsNot

Inequality of two objects

emp IsNot mgr

True if emp and mgr refer to different objects

TypeOf ... Is

Object is of a certain type

TypeOf(obj) Is Manager

True if obj points to a Manager object

Like

Matches a text pattern

A Like "###-####"

True if A contains three digits, a dash, and four digits

The Is operator returns True if its two operands refer to the same object. For example, if you create an Order object and make two different variables, A and B, point to it, the expression A Is B is True. Note that Is returns False if the two operands point to different Order objects that happen to have the same property values.

The IsNot operator is simply shorthand for a more awkward Not . . . Is construction. For example, the statement A IsNot Nothing is equivalent to Not (A Is Nothing).

The value Nothing is a special value that means not an object. If you have an object variable, you can use the Is or IsNot operator to compare it to Nothing to see if it represents anything. Note that you cannot use Is or IsNot to compare an object variable to 0 or some other numeric value. Is and IsNot only work with objects such as those stored in variables and the special value Nothing.

The TypeOf operator returns True if its operand is of a certain type. This operator is particularly useful when a subroutine takes a parameter that could be of more than one object type. It can use TypeOf to see which type of object it has.

The Like operator returns True if its first operand matches a pattern specified by its second operand. Where the pattern includes normal characters, the string must match those characters exactly. The pattern can also include several special character sequences summarized in the following table.

CHARACTER(S)

MEANING

?

Matches any single character

*

Matches any zero or more characters

#

Matches any single digit

[characters]

Matches any of the characters between the brackets

[!characters]

Matches any character not between the brackets

A-Z

When inside brackets, matches any character in the range A to Z

You can combine ranges of characters and individual characters inside brackets. For example, the pattern [a-zA-Z] matches any letter between a and z or between A and Z. The following table lists some useful patterns for use with the Like operator.

PATTERN

MEANING

[2-9]##-####

Seven-digit U.S. phone number

[2-9]##-[2-9]##-####

Ten-digit phone number, including area code

1-[2-9]##-[2-9]##-####

Eleven-digit phone number, beginning with 1 and area code

#####

Five-digit ZIP code

#####-####

Nine-digit ZIP + 4 code

?*@?*.?*

E-mail address

For example, the following code checks whether the text box txtPhone contains something that looks like a 10-digit phone number:

If Not (txtPhone.Text Like "[2-9]##-[2-9]##-####") Then
    MessageBox.Show("Please enter a valid pohone number")
End If

These patterns are not completely foolproof. For example, the e-mail address pattern verifies that the string contains at least one character, an @ character, at least one other character, a dot, and at least one more character. For example, it allows . However, it does not verify that the extension makes sense, so it also allows , and it allows more than one @ character, as in .

Regular expressions provide much more powerful pattern-matching capabilities. The section "Regular Expressions" in Chapter 40, "Useful Namespaces," contains more information about regular expressions.

LOGICAL OPERATORS

Logical operators combine two Boolean values and return True or False, depending on the result. The following table summarizes Visual Basic's logical operators.

OPERATOR

PURPOSE

EXAMPLE

RESULT

Not

Logical or bitwise negation

Not A

True if A is false

And

Logical or bitwise And

A And B

True if A and B are both true

Or

Logical or bitwise Or

A Or B

True if A or B or both are true

Xor

Logical or bitwise exclusive Or

A Xor B

True if A or B but not both is true

AndAlso

Logical or bitwise And with short-circuit evaluation

A AndAlso B

True if A and B are both true (see the following notes)

OrElse

Logical or bitwise Or with short-circuit evaluation

A OrElse B

True if A or B or both are true (see notes)

The operators Not, And, and Or are relatively straightforward.

"Xor" stands for "exclusive or," and the Xor operator returns True if one but not both of its operands is true. The expression A Xor B is true if A is true or B is true but both are not true.

Xor is useful for situations where exactly one of two things should be true. For example, suppose you're running a small software conference with two tracks so two talks are going on at any given time. Each attendee should sign up for one talk in each time slot but cannot sign up for both because they're at the same time. Then you might use code similar to the following to check whether an attendee has signed up for either talk 1a or talk 1b but not both.

If talk1a Xor talk1b Then
    ' This is okay
    ...
End If

The AndAlso and OrElse operators are similar to the And and Or operators, except that they provide short-circuit evaluation. In short-circuit evaluation, Visual Basic is allowed to stop evaluating operands if it can deduce the final result without them. For example, consider the expression A AndAlso B. If Visual Basic evaluates the value A and discovers that it is false, the program knows that the expression A AndAlso B is also false no matter what value B has, so it doesn't need to evaluate B.

Whether the program evaluates both operands doesn't matter much if A and B are simple Boolean variables. However, assume that they are time-consuming functions in the following code. For example, the TimeConsumingFunction function might need to look up values in a database or download data from a web site. In that case, not evaluating the second operand might save a lot of time.

If TimeConsumingFunction("A") AndAlso TimeConsumingFunction("B") Then ...

Just as AndAlso can stop evaluation if it discovers one of its operands is False, the OrElse operand can stop evaluating if it discovers that one of its operands is True. The expression A OrElse B is True if either A or B is True. If the program finds that A is True, it doesn't need to evaluate B.

Because AndAlso and OrElse do the same thing as And and Or but sometimes faster, you might wonder why you would ever use And and Or. The main reason is that the operands may have side effects. A side effect is some action a routine performs that is not obviously part of the routine. For example, suppose that the NumEmployees function opens an employee database and returns the number of employee records, leaving the database open. The fact that this function leaves the database open is a side effect.

Now, suppose that the NumCustomers function similarly opens the customer database, and then consider the following statement:

If (NumEmployees() > 0) AndAlso (NumCustomers() > 0) Then ...

After this code executes, you cannot be certain which databases are open. If NumEmployees returns 0, the AndAlso operator's first operand is False, so it doesn't evaluate the NumCustomers function and that function doesn't open the customer database.

The AndAlso and OrElse operators can improve application performance under some circumstances. However, to avoid possible confusion and long debugging sessions, do not use AndAlso or OrElse with operands that have side effects.

BITWISE OPERATORS

Bitwise operators work much like logical operators do, except they compare values one bit at a time. The bitwise negation operator Not flips the bits in its operand from 1 to 0 and vice versa. The following shows an example:

10110111
Not 01001000

The And operator places a 1 in a result bit if both of the operands have a 1 in that position. The following shows the results of combining two binary values by using the bitwise And operator:

10101010
And 00110110
    00100010

The bitwise Or operator places a 1 bit in the result if either of its operands has a 1 in the corresponding position. The following shows an example:

10101010
Or 00110110
   10111110

The bitwise Xor operator places a 1 bit in the result if exactly one of its operands, but not both, has a 1 in the corresponding position. The following shows an example:

10101010
Xor 00110110
    10011100

There are no bitwise equivalents for the AndAlso and OrElse operators.

OPERATOR PRECEDENCE

When Visual Basic evaluates a complex expression, it must decide the order in which to evaluate operators. For example, consider the expression 1 + 2 * 3 / 4 + 2. The following text shows three orders in which you might evaluate this expression to get three different results:

1 + (2 * 3) / (4 + 2) = 1 + 6 / 6 = 2
1 + (2 * 3 / 4) + 2 = 1 + 1.5 + 2 = 4.5
(1 + 2) * 3 / (4 + 2) = 3 * 3 / 6 = 1.5

Precedence determines which operator Visual Basic executes first. For example, the Visual Basic precedence rules say the program should evaluate multiplication and division before addition, so the second equation is correct.

The following table lists the operators in order of precedence. When evaluating an expression, the program evaluates an operator before it evaluates those lower than it in the list.

OPERATOR

DESCRIPTION

( )

Grouping (parentheses)

^

Exponentiation

-

Negation

*, /

Multiplication and division

Integer division

Mod

Modulus

+, -, +

Addition, subtraction, and concatenation

&

Concatenation

<<, >>

Bit shift

=, <>, <, <=, >, >=, Like, Is, IsNot, TypeOf ... Is

All comparisons

Not

Logical and bitwise negation

And, AndAlso

Logical and bitwise And with and without short-circuit evaluation

Xor, Or, OrElse

Logical and bitwise Xor, and Or with and without short-circuit evaluation

When operators are on the same line in the table, or if an expression contains more than one instance of the same operator, the program evaluates them in left-to-right order. For example, * and / are on the same line in the table so in the expression 12 * 4 / 20 Visual Basic would perform the multiplication first. (Of course, it wouldn't matter much in this example because the result should be the same either way, at least within the limits of the computer's precision.)

Parentheses are not really operators, but they do have a higher precedence than the true operators, so they're listed to make the table complete. You can always use parentheses to explicitly dictate the order in which Visual Basic will perform an evaluation.

If there's the slightest doubt about how Visual Basic will handle an expression, add parentheses to make it obvious. Even if you can easily figure out what an expression means, parentheses often make the code even easier to read and understand. There's no extra charge for using parentheses, and they may avoid some unnecessary confusion.

ASSIGNMENT OPERATORS

Visual Basic has always had the simple assignment operator =. Visual Basic .NET added several new assignment operators to handle some common statements where a value was set equal to itself combined with some other value. For example, the following two statements both add the value 10 to the variable iterations:

iterations = iterations + 10 ' Original syntax.
iterations += 10 ' New syntax.

All the other assignment operators work similarly by adding an equals sign to an arithmetic operator. For example, the statement A ^= B is equivalent to A = A ^ B.

You can still use the original syntax if you like. However, the new syntax sometimes gives you better performance. If the left-hand side of the assignment is not a simple variable, Visual Basic may be able to save time by evaluating it only once. For example, the following code adds 0.1 to a customer order's discount value. By using +=, the code allows Visual Basic to find the location of this value only once.

Customers(cust_num).Orders(order_num).Discount += 0.1

The complete list of assignment operators is: =, ^=, *=, /=, =, +=, -=, &=, <<=, and >>=.

If you have Option Strict set to On, the variables must have the appropriate data types. For example, /= returns a Double, so you cannot use that operator with an Integer, as in the following code:

Dim i As Integer = 100
i /= 2                       ' Not allowed.

To perform this operation, you must explicitly convert the result into an Integer, as shown in the following statement:

i = CInt(i / 2)

This makes sense because you are trying to assign the value of floating-point division to an Integer. It's less obvious why the following code is also illegal. Here the code is trying to assign an Integer result to a Single variable, so you might think it should work. After all, an Integer value will fit in a Single variable.

Dim x As Single
x = 10                     ' Not allowed.

The problem isn't in the assignment, but in performing the calculation. The following statement is equivalent to the previous one, and it is also illegal:

x = x  10                  ' Not allowed.

The problem with both of these statements is that the operator takes as arguments two Integers. If Option Strict is on, the program will not automatically convert a floating-point variable into an Integer for the operator. To make this statement work, you must manually convert the variable into an Integer data type, as shown in the following example:

x = CLng(x)  10 ' Allowed.

The += and &= operators both combine strings but &= is less ambiguous, so you should use it whenever possible. It may also give you better performance because it explicitly tells Visual Basic that the operands are strings.

THE STRINGBUILDER CLASS

The & and &= operators are useful for concatenating a few strings together. However, if you must combine a large number of strings, you may get better performance using the StringBuilder class. This class is optimized for performing long sequences of concatenations to build big strings.

For small pieces of code, the difference between using a String and a StringBuilder is not noticeable. If you need only to concatenate a dozen or so strings once, using a StringBuilder won't make much difference in runtime and may even slow performance slightly.

However, if you make huge strings built up in pieces, or if you build simpler strings but many times in a loop, StringBuilder may make your program run faster.

Example program StringBuilderTest1, which is available for download on the book's web site, uses the following code to compare the speeds of building a long string with and without the StringBuilder class:

Private Sub btnGo_Click() Handles btnGo.Click
    Const ADD_STRING As String = "1234567890"
    Dim num_trials As Long = Long.Parse(txtNumTrials.Text)
    Dim start_time As DateTime
    Dim stop_time As DateTime
    Dim elapsed_time As TimeSpan
    Dim txt As String
    Dim string_builder As New StringBuilder

    lblString.Text = ""
    lblStringBuilder.Text = ""
    Application.DoEvents()

    txt = ""
    start_time = Now
    For i As Long = 1 To num_trials
        txt = txt & ADD_STRING
    Next i
    stop_time = Now
    elapsed_time = stop_time.Subtract(start_time)
    lblString.Text = elapsed_time.TotalSeconds.ToString("0.000000")
txt = ""
    start_time = Now
    For i As Long = 1 To num_trials
        string_builder.Append(ADD_STRING)
    Next i
    txt = string_builder.ToString()
    stop_time = Now
    elapsed_time = stop_time.Subtract(start_time)
    lblStringBuilder.Text = elapsed_time.TotalSeconds.ToString("0.000000")
End Sub
                                                  
THE STRINGBUILDER CLASS

The code concatenates the string 1234567890 a large number of times, first using a String variable and then using a StringBuilder. In one test that performed the concatenation 10,000 times to build strings 100,000 characters long, using a String took roughly 1.6 seconds. Using a StringBuilder, the program was able to build the string in roughly 0.001 seconds.

Admittedly, building such enormous strings is not a common programming task. Even when the strings are shorter, you can sometimes see a noticeable difference in performance, particularly if you must build a large number of such strings.

Example program StringBuilderTest2, which is also available for download, uses the following code to concatenate the string 1234567890 to itself 100 times, making a string 1,000 characters long. It builds the string repeatedly for a certain number of trials. In one test building the 1,000-character string 10,000 times, using a String took around 0.95 seconds, whereas using a StringBuilder took about 0.06 seconds.

Private Sub btnGo_Click() Handles btnGo.Click
    Const ADD_STRING As String = "1234567890"
    Dim num_trials As Long = Long.Parse(txtNumTrials.Text)
    Dim start_time As DateTime
    Dim stop_time As DateTime
    Dim elapsed_time As TimeSpan
    Dim txt As String
    Dim string_builder As New StringBuilder

    lblString.Text = ""
    lblStringBuilder.Text = ""
    Application.DoEvents()

    start_time = Now
    For i As Long = 1 To num_trials
        txt = ""
        For j As Long = 1 To 100
            txt = txt & ADD_STRING
        Next j
    Next i
    stop_time = Now
    elapsed_time = stop_time.Subtract(start_time)
    lblString.Text = elapsed_time.TotalSeconds.ToString("0.000000")
txt = ""
    start_time = Now
    For i As Long = 1 To num_trials
        string_builder = New StringBuilder
        For j As Long = 1 To 100
            string_builder.Append(ADD_STRING)
        Next j
        txt = string_builder.ToString()
    Next i
    stop_time = Now
    elapsed_time = stop_time.Subtract(start_time)
    lblStringBuilder.Text = elapsed_time.TotalSeconds.ToString("0.000000")
End Sub
                                                  
THE STRINGBUILDER CLASS

Strings and string operations are a bit more intuitive than the StringBuilder class, so your code will usually be easier to read if you use String variables when performance isn't a big issue. If you are building enormous strings, or are building long strings a huge number of times, the performance edge given by the StringBuilder class may be worth slightly more complicated-looking code.

DATE AND TIMESPAN OPERATIONS

The Date data type is fundamentally different from other data types. When you perform an operation on most data types, you get a result that has the same data type or that is at least of some compatible data type. For example, if you subtract two Integer variables, the result is an Integer. If you divide two Integers using the / operator, the result is a Double. That's not another Integer, but it is a compatible numeric data type used because an Integer cannot always hold the result of a division.

If you subtract two Date variables, however, the result is not a Date. For example, what's August 7 minus July 20? It doesn't make sense to think of the result as a Date. Instead, Visual Basic defines the difference between two Dates as a TimeSpan. A TimeSpan measures the elapsed time between two Dates. In this example, August 7 minus July 20 is 18 days. (And yes, TimeSpans know all about leap years.)

The following equations define the arithmetic of Dates and TimeSpans:

  • Date - Date = TimeSpan

  • Date + TimeSpan = Date

  • TimeSpan + TimeSpan = TimeSpan

  • TimeSpan - TimeSpan = TimeSpan

The TimeSpan class also defines unary negation (ts2 = -ts1), but other operations (such as multiplying a TimeSpan by a number) are not defined. However, in some cases, you can still perform the calculation if you must.

Example program MultiplyTimeSpan, which is available for download on the book's web site, uses the following statement to make the TimeSpan ts2 equal to 12 times the duration of TimeSpan ts1:

ts2 = New TimeSpan(ts1.Ticks * 12)

Starting with Visual Basic 2005, the +, -, <, >, <=, >=, <>, and = operators are defined for Dates and TimeSpans. Previous versions did not define these operators, but the Date class did provide equivalent operator methods. For example, the Date class's op_Subtraction method subtracts two Dates and returns a TimeSpan.

These operator methods are still available and you may want to use them if you find using the normal operator symbols less clear. The following table lists the Date operator methods. Note that the Common Language Runtime name for the Date data type is DateTime, so you need to look for DateTime in the online help for more information on these methods.

SYNTAX

MEANING

result_date = Date.op_Addition(date1, timespan1)

Returns date1 plus timespan1

result_boolean = Date.op_Equality(date1, date2)

True if date1>date2

result_boolean = Date.op_GreaterThan(date1, date2)

True if date1>date2

result_boolean = Date.op_GreaterThanOrEqual(date1, date2)

True if date1>= date2

result_boolean = Date.op_Inequality(date1, date2)

True if date1<>date2

result_boolean = Date.op_LessThan(date1, date2)

True if date1<date2

result_boolean = Date.op_LessThanOrEqual(date1, date2)

True if date1<= date2

result_timespan = Date.op_Subtraction(date1, date2)

Returns the TimeSpan between date1 and date2

result = Date.Compare(date1, date2)

Returns a value indicating whether date1 is greater than, less than, or equal to date2

The Compare method is a bit different from the others, returning an Integer rather than a Boolean or Date. Its value is less than zero if date1 < date2, greater than zero if date1 > date2, and equal to zero if date1 = date2.

These are shared methods, so you do not need to use a specific instance of the Date data type to use them. For example, the following code displays the number of days between July 20 and August 7:

Dim date1 As Date = #7/20/04#
Dim date2 As Date = #8/7/04#
Dim elapsed_time As TimeSpan

    elapsed_time = Date.op_Subtraction(date2, date1)
    Debug.WriteLine(elapsed_time.Days)

These operators are a bit cumbersome. To make these kinds of calculations easier, the Date data type provides other methods for performing common operations that are a bit easier to read. Whereas the operator methods take both operands as parameters, these methods take a single operand as one parameter and use the current object as the other. For example, a Date object's Add method adds a TimeSpan to the date and returns the resulting date. The following table summarizes these methods.

SYNTAX

MEANING

result_date = date1.Add(timespan1)

Returns date1 plus timespan1

result_date = date1.AddYears(num_years)

Returns the date plus the indicated number of years

result_date = date1.AddMonths(num_months)

Returns the date plus the indicated number of months

result_date = date1.AddDays (num_days)

Returns the date plus the indicated number of days

result_date = date1.AddHours(num_hours)

Returns the date plus the indicated number of hours

result_date = date1.AddMinutes(num_minutes)

Returns the date plus the indicated number of minutes

result_date = date1.AddSeconds(num_seconds)

Returns the date plus the indicated number of seconds

result_date = date1.AddMilliseconds(num_milliseconds)

Returns the date plus the indicated number of milliseconds

result_date = date1.AddTicks (num_ticks)

Returns the date plus the indicated number of ticks (100-nanosecond units)

result_timespan = date1.Subtract (date2)

Returns the time span between date2 and date1

result_integer = date1.CompareTo (date2)

Returns a value indicating whether date1 is greater than, less than, or equal to date2

result_boolean = date1.Equals(date2)

Returns True if date1 equals date2

The CompareTo method returns a value less than zero if date1 < date2, greater than zero if date1 > date2, and equal to zero if date1 = date2.

OPERATOR OVERLOADING

Visual Basic defines operators for expressions that use standard data types such as Integers and Boolean values. It defines a few operators such as Is and IsNot for objects, but operators such as * and Mod don't make sense for objects in general.

Nevertheless, you can also define those operators for your structures and classes, if you like, by using the Operator statement. This is a more advanced topic, so if you're new to Visual Basic, you may want to skip this section and come back to it later, perhaps after you have read Chapter 26, "Classes and Structures."

The general syntax for operator overloading is:

[ <attributes> ] Public [ Overloads ] Shared [ Shadows ] _
 [ Widening | Narrowing ] Operator symbol ( operands ) As type
    ...
End Operator

The parts of this declaration are:

  • attributes — Attributes for the operator.

  • Public — All operators must be Public Shared.

  • Overloads — You can only use this if the operator takes two parameters that are from a base class and a derived class as its two operators. In that case, it means the operator overrides the operator defined in the base class.

  • Shared — All operators must be Public Shared.

  • Shadows — The operator replaces a similar operator defined in the base class.

  • Widening — Indicates that the operator defines a widening conversion that always succeeds at runtime. For example, an Integer always fits in a Single, so storing an Integer in a Single is a widening operation. This operator must catch and handle all errors. The CType operator must include either the Widening or Narrowing keyword.

  • Narrowing — Indicates that the operator defines a narrowing conversion that may fail at runtime. For example, a Single does not necessarily fit in an Integer, so storing a Single in an Integer is a narrowing operation. The CType operator must include either the Widening or Narrowing keyword.

  • symbol — The operator's symbol. This can be +, −, *, /, , ^, &, <<, >>, =, <>, <, >, <=, >=, Mod, Not, And, Or, Xor, Like, IsTrue, IsFalse, or CType.

  • operands — Declarations of the objects to be manipulated by the operator. The unary operators +, −, Not, IsTrue, and IsFalse take a single operand. The binary operators +, −, *, /, , ^, &, <<, >>, =, <>, <, >, <=, >=, Mod, And, Or, Xor, Like, and CType take two operands.

  • type — All operators must have a return type and must return a value by using a Return statement.

Operator overloading is subject to several constraints:

  • Some operands come in pairs, and if you define one you must define the other. The pairs are = and <>, < and >, <= and >=, and IsTrue and IsFalse.

  • For the standard unary or binary operators, the class or structure that defines the operator must appear in an operand. For the CType conversion operator, the class or structure must appear in the operand or return type.

  • The IsTrue and IsFalse operators must return Boolean values.

  • The second operands for the << and >> operators must be Integers.

If you define an operator, Visual Basic automatically provides the corresponding assignment operator. For example, if you define the + operator, Visual Basic provides the += assignment operator.

Though you cannot use the IsTrue and IsFalse operators directly, you can use them indirectly. If you define IsTrue for a class, Visual Basic uses it to determine whether an object should be treated as True in a Boolean expression. For example, the following statement uses the IsTrue operator to decide whether the object c1 should be considered True:

if c1 Then ...

If you define the And and IsFalse operators, Visual Basic uses them to handle the AndAlso operator as well. For this to work, the And operator must return the same type of class or structure where you define it. For example, suppose you have defined And and IsFalse for the Composite class and suppose variables c1, c2, and c3 are all instances of this class. Then consider the following statement:

c3 = c1 AndAlso c2

Visual Basic uses IsFalse to evaluate c1. If IsFalse returns True, the program doesn't bother to evaluate c2. Instead it assumes the whole statement is False and returns a False value. Because IsFalse returned True for c1, Visual Basic knows that c1 is a False value, so it sets c3 equal to c1.

This is pretty confusing. It may make more sense if you think about how Visual Basic evaluates Boolean expressions that use the normal AndAlso operator.

Similarly, if you define the Or and IsTrue operators, Visual Basic automatically provides the OrElse operator.

Although you generally cannot make two versions of a function in Visual Basic that differ only in their return types, you can do that for CType conversion operators. When the program tries to make a conversion, Visual Basic can tell by the type of the result which conversion operator to use.

Example program ComplexNumbers, which is available for download on the book's web site, uses the following code to define a Complex class that represents a complex number. It defines +, -, and * operators to implement normal addition, subtraction, and multiplication on complex numbers. It also defines =, <>, and unary negation operators, and a conversion operator that converts a Complex object into a Double by returning its magnitude.

Public Class Complex
    Public Re As Double
    Public Im As Double

    ' Constructors.
    Public Sub New()
    End Sub
    Public Sub New(ByVal real_part As Double, ByVal imaginary_part As Double)
         Re = real_part
         Im = imaginary_part
    End Sub

    ' ToString.
    Public Overrides Function ToString() As String
          Dim txt As String = Re.ToString
          If Im < 0 Then
             txt &= " - " & Math.Abs(Im).ToString
          Else
             txt &= " + " & Im.ToString
          End If
          Return txt & "i"
    End Function

    ' Operators.
    Public Shared Operator *(ByVal c1 As Complex, ByVal c2 As Complex) _
     As Complex
          Return New Complex(
              c1.Re * c2.Re - c1.Im * c2.Im,
              c1.Re * c2.Im + c1.Im * c2.Re)
    End Operator
    Public Shared Operator +(ByVal c1 As Complex, ByVal c2 As Complex) _
     As Complex
          Return New Complex(
              c1.Re + c2.Re,
              c1.Im + c2.Im)
    End Operator
    Public Shared Operator -(ByVal c1 As Complex, ByVal c2 As Complex) _
     As Complex
          Return New Complex(
              c1.Re - c2.Re,
              c1.Im - c2.Im)
    End Operator
    Public Shared Operator =(ByVal c1 As Complex, ByVal c2 As Complex) _
As Boolean
          Return (c1.Re = c2.Re) AndAlso (c1.Im = c2.Im)
    End Operator
    Public Shared Operator <>(ByVal c1 As Complex, ByVal c2 As Complex) _
     As Boolean
          Return (c1.Re <> c2.Re) OrElse (c1.Im <> c2.Im)
    End Operator
    Public Shared Operator -(ByVal c1 As Complex) As Complex
          Return New Complex(-c1.Re, -c1.Im)
    End Operator
    Public Shared Narrowing Operator CType(ByVal c1 As Complex) As Double
          Return System.Math.Sqrt(c1.Re * c1.Re + c1.Im * c1.Im)
    End Operator
End Class
                                                  
OPERATOR OVERLOADING

It is easy to get carried away with operator overloading. Just because you can define an operator for a class doesn't mean you should. For example, you might be able to concoct some meaning for addition with the Employee class, but it would probably be a counterintuitive operation. You would probably be better off writing a subroutine or function with a meaningful name instead of using an ambiguous operator such as + or >>.

OPERATORS WITH NULLABLE TYPES

Chapter 15, "Data Types, Variables, and Constants," describes nullable types. A variable declared as nullable can distinguish between holding zero, blank, and other "trivial" values and holding no data at all. For example, if you declare the variable x as a nullable Integer, you can set it to the special value Nothing to indicate that it doesn't contain any data.

If all of the operands in an expression contain actual values rather than Nothing, then arithmetic, comparison, logical, or bitwise operations return the values you would expect. If one or more nullable variables in an expression contains the special value Nothing, Visual Basic uses special "null-propagation" rules for evaluating the expression.

If one or more of the operands in an arithmetic, comparison, logical, or bitwise operation is Nothing, the result is also Nothing. For example, if x and y are nullable and x contains no value, the following expressions, and just about any other expression containing x, have the value Nothing.

-x
x + y
x * y
x ^ y
x >> y

For more information about nullable types, seeChapter 15.

SUMMARY

A program uses operators to manipulate variables, constants, and literal values to produce new results. The Visual Basic operators fall into five categories: arithmetic, concatenation, comparison, logical, and bitwise. In most cases, using operators is straightforward and intuitive.

Operator precedence determines the order in which Visual Basic applies operators when evaluating an expression. In cases where an expression's operator precedence is unclear, add parentheses to make the order obvious. Even if you don't change the way that Visual Basic handles the statement, you can make the code more understandable and avoid possibly time-consuming bugs.

The String data type has its own special needs. String manipulation plays a big role in many applications, so Visual Basic provides a StringBuilder class for manipulating strings more efficiently. On the one hand, if your program only works with a few short strings, it probably doesn't need to use a StringBuilder, and using the String data type will probably make your code easier to understand. On the other hand, if your application builds enormous strings or concatenates a huge number of strings, you may be able to save a noticeable amount of time using the StringBuilder class.

The Date data type also behaves differently from other data types. The normal operators such as + and - have different meanings here from other data types. For example, a Date minus a Date gives a TimeSpan, not another Date. These operations generally make sense if you think carefully about what dates and time spans are.

Just as addition, subtraction, and the other operators have special meaning for Dates and TimeSpans, you can use operator overloading to define operators for your classes. Defining division or exponentiation may not make much sense for Employees, Customer, or Orders, but in some cases custom operators can make your code more readable. For example, you might imagine the following statement adding an OrderItem to a CustomerOrder:

the_order += new_item

This chapter explains how to use operators to combine variables to calculate new results. A typical program may perform the same set of calculations many times for different variable values. Although you might be able to perform those calculations in a long series, the resulting code would be cumbersome and hard to maintain. Chapter 17, "Subroutines and Functions," explains how you can use subroutines and functions to break a program into manageable pieces that you can then reuse to make performing the calculations easier and more uniform.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.79.84