在 Visual Basic 教程的这一部分中,我们将讨论运算符。
运算符是特殊符号,表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。
我们有几种类型的运算符:
- 算术运算符
- 布尔运算符
- 关系运算符
- 按位运算符
一个运算符可以有一个或两个操作数。 操作数是运算符的输入(参数)之一。 仅使用一个操作数的那些运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。
Option Strict On
Module Example
Sub Main()
Console.WriteLine(2)
Console.WriteLine(-2)
Console.WriteLine(2+2)
Console.WriteLine(2-2)
End Sub
End Module
+和-可以是加减运算符,也可以是一元符号运算符。 这取决于实际情况。
Option Strict On
Module Example
Dim a As Byte
Sub Main()
a = 1
Console.WriteLine(-a) ' Prints -1
Console.WriteLine(-(-a)) ' Prints 1
End Sub
End Module
加号可以用来表示我们有一个正数。 但是它通常不被使用。 减号更改值的符号。
Option Strict On
Module Example
Dim a As Byte
Dim b As Byte
Sub Main()
a = 3 * 3
b = 2 + 2
Console.WriteLine(a) ' Prints 9
Console.WriteLine(b) ' Print 4
End Sub
End Module
乘法和加法运算符是二进制运算符的示例。 它们与两个操作数一起使用。
赋值运算符
赋值运算符=
将值赋给变量。 variable
是值的占位符。 在数学中,=
运算符具有不同的含义。 在等式中,=
运算符是一个相等运算符。 等式的左侧等于右侧。
x = 1
Console.WriteLine(x) ' Prints 1
在这里,我们为x
变量分配一个数字。
x = x + 1
Console.WriteLine(x)
先前的表达式在数学上没有意义。 但这在编程中是合法的。 该表达式将x
变量加 1。 右边等于 2,并且 2 分配给x
。
3 = x
此代码示例导致语法错误。 我们无法为字面值分配值。
算术运算符
下表是 Visual Basic 中的算术运算符表。
符号 | 名称 |
---|---|
+ |
加法 |
- |
减法 |
* |
乘法 |
/ |
除法 |
\ |
整数除法 |
Mod |
模数 |
^ |
求幂 |
以下示例显示了算术运算。
Option Strict On
Module Example
Dim a As Byte
Dim b As Byte
Dim c As Byte
Dim add As Byte
Dim sb As Byte
Dim mult As Byte
Dim div As Byte
Sub Main()
a = 10
b = 11
c = 12
add = a + b + c
sb = c - a
mult = a * b
div = CType(c / 3, Byte)
Console.WriteLine(add)
Console.WriteLine(sb)
Console.WriteLine(mult)
Console.WriteLine(div)
End Sub
End Module
在前面的示例中,我们使用加,减,乘和除运算。 这些都是数学所熟悉的。
$ ./arithmetic.exe
33
2
110
4
示例的输出。
接下来,我们将说明正态除法和整数除法之间的区别。
Option Strict On
Module Example
Dim a As Single = 5
Dim b As Single = 2
Dim c As Single
Sub Main()
c = 5 / 2
Console.WriteLine(c)
c = 5 \ 2
Console.WriteLine(c)
End Sub
End Module
在前面的示例中,我们使用普通和整数除法运算符对两个数进行除法。 Visual Basic 有两个不同的除法运算符。
Dim a As Single = 5
我们使用浮点数据类型。
c = 5 / 2
Console.WriteLine(c)
这是“正常”的分割操作。 它返回 2.5,如预期的那样。
c = 5 \ 2
Console.WriteLine(c)
这是整数除法。 此操作的结果始终为整数。 c
变量的值为 2。
$ ./division.exe
2.5
2
division.exe
程序的结果。
我们将提到的最后两个运算符是模运算符和幂运算符。
Console.WriteLine(9 Mod 4) ' Prints 1
Mod
运算符称为模运算符。 它找到一个数除以另一个的余数。 9 Mod 4
,9 模 4 为 1,因为 4 两次乘以 9,余数为 1。例如,当我们要检查素数时,模运算符会很方便。
最后,我们将提到求幂运算符。
Console.WriteLine(9 ^ 2) ' Prints 81
9 ^ 2 = 9 * 9 = 81
连接字符串
在 Visual Basic 中,我们有两个用于字符串连接的运算符。 加号+
运算符和&
和号运算符。
Option Strict On
Module Example
Sub Main()
Console.WriteLine("Return " & "of " & "the king")
Console.WriteLine("Return " + "of " + "the king")
End Sub
End Module
我们使用两个运算符将三个字符串连接在一起。
$ ./concatstrings.exe
Return of the king
Return of the king
这就是我们得到的。 两种情况的结果相同。
布尔运算符
在 Visual Basic 中,我们具有以下逻辑运算符。 布尔运算符也称为逻辑运算符。
符号 | 名称 |
---|---|
And |
逻辑与 |
AndAlso |
短路与 |
Or |
逻辑或 |
OrElse |
短路或 |
Xor |
逻辑异或 |
Not |
否定 |
布尔运算符用于处理真值。
Option Strict On
Module Example
Dim x As Byte = 3
Dim y As Byte = 8
Sub Main()
Console.WriteLine(x = y)
Console.WriteLine(y > x)
If (y > x)
Console.WriteLine("y is greater than x")
End If
End Sub
End Module
许多表达式导致布尔值。 布尔值用于条件语句中。
Console.WriteLine(x = y)
Console.WriteLine(y > x)
关系运算符始终导致布尔值。 这两行显示False
和True
。
If (y > x)
Console.WriteLine("y is greater than x")
End If
仅在满足括号内的条件时才执行If
语句的主体。 x > y
返回True
,因此消息"y
大于x"
被打印到终端。
Option Strict On
Module Example
Dim a As Boolean
Dim b As Boolean
Dim c As Boolean
Dim d As Boolean
Sub Main()
a = (True And True)
b = (True And False)
c = (False And True)
d = (False And False)
Console.WriteLine(a)
Console.WriteLine(b)
Console.WriteLine(c)
Console.WriteLine(d)
End Sub
End Module
示例显示了逻辑And
运算符。 仅当两个操作数均为True
时,它的求值结果为True
。
$ ./andop.exe
True
False
False
False
如果正好一个操作数为True
,则逻辑Xor
运算符的计算结果为True
。
Option Strict On
Module Example
Dim a As Boolean
Dim b As Boolean
Dim c As Boolean
Dim d As Boolean
Sub Main
a = (True Xor True)
b = (True Xor False)
c = (False Xor True)
d = (False Xor False)
Console.WriteLine(a)
Console.WriteLine(b)
Console.WriteLine(c)
Console.WriteLine(d)
End Sub
End Module
如果两个操作数均为True
或均为False
,则逻辑Xor
的计算结果为False
。
$ ./xorop.exe
False
True
True
False
如果两个操作数中的任何一个为True
,则逻辑Or
运算符的计算结果为True
。
Option Strict On
Module Example
Sub Main()
Dim a As Boolean = True Or True
Dim b As Boolean = True Or False
Dim c As Boolean = False Or True
Dim d As Boolean = False Or False
Console.WriteLine(a)
Console.WriteLine(b)
Console.WriteLine(c)
Console.WriteLine(d)
End Sub
End Module
如果运算符的任一侧为 True,则运算结果为 True。
$ ./orop.exe
True
True
True
False
否定运算符Not
设为True False
和False True
。
Option Strict On
Module Example
Sub Main()
Console.WriteLine(Not True)
Console.WriteLine(Not False)
Console.WriteLine(Not (4 < 3))
End Sub
End Module
该示例显示了否定运算符的作用。
$ ./negation.exe
False
True
True
AndAlso
和OrElse
运算符经过短路求值。 短路求值意味着仅当第一个参数不足以确定表达式的值时才求值第二个参数:当And
的第一个参数求值为false
时,总值必须为false
; 并且当Or
的第一个参数计算为true
时,总值必须为true
。 (维基百科)短路求值主要用于提高性能。
一个例子可以使这一点更加清楚。
Option Strict On
Module Example
Sub Main()
Console.WriteLine("Short circuit")
If (one AndAlso two)
Console.WriteLine("Pass")
End If
Console.WriteLine("#############")
If (one And two)
Console.WriteLine("Pass")
End If
End Sub
Function one As Boolean
Console.WriteLine("Inside one")
Return False
End Function
Function two As Boolean
Console.WriteLine("Inside two")
Return True
End Function
End Module
在示例中,我们有两个函数。 函数与子例程不同,返回值。 这是它们之间的主要区别。
If (one AndAlso two)
Console.WriteLine("Pass")
End If
一个函数返回False
。 短路AndAlso
不求值第二功能。 没有必要。 一旦操作数为False
,逻辑结论的结果始终为False
。 控制台上仅打印"Inside one"
。
Console.WriteLine("#############")
If (one And two)
Console.WriteLine("Pass")
End If
在第二种情况下,我们使用And
。 在这种情况下,两个函数都被调用。 即使表达式的结果不是必需的。
$ ./shorcircuit.exe
Short circuit
Inside one
#############
Inside one
Inside two
shorcircuit.exe
程序的结果。
关系运算符
关系运算符用于比较值。 这些运算符总是产生布尔值。
符号 | 含义 |
---|---|
< |
小于 |
<= |
小于或等于 |
> |
大于 |
>= |
大于或等于 |
== |
等于 |
<> |
不等于 |
Is |
比较引用 |
关系运算符也称为比较运算符。
Console.WriteLine(3 < 4) ' Prints True
Console.WriteLine(3 = 4) ' Prints False
Console.WriteLine(4 >= 3) ' Prints True
正如我们已经提到的,关系运算符返回布尔值。 请注意,在 Visual Basic 中,比较运算符为=
。 不像受 C 和 C 影响的语言那样==
。
注意,关系运算符不限于数字。 我们也可以将它们用于其他对象。 尽管它们可能并不总是有意义的。
Option Strict On
Module Example
Sub Main()
Console.WriteLine("six" = "six") ' Prints True
' Console.WriteLine("a" > 6) this would throw
' an exception
Console.WriteLine("a" < "b") ' Prints True
End Sub
End Module
我们也可以比较字符串对象。 字符串上下文中的比较运算符比较字符的排序顺序。
Console.WriteLine("a" < "b") ' Prints True
这里到底发生了什么? 计算机不知道字符或字符串。 对于他们来说,一切都只是数字。 字符是存储在特定表中的特殊数字。 类似于 ASCII。
Option Strict On
Module Example
Sub Main()
Console.WriteLine("a" < "b")
Console.WriteLine("a is: {0}", Asc("a"))
Console.WriteLine("b is: {0}", Asc("b"))
End Sub
End Module
在内部,a 和 b 字符是数字。 因此,当我们比较两个字符时,我们将比较它们的存储数字。 内置的Asc
函数返回单个字符的 ASCII 值。
$ ./compare.exe
True
a is: 97
b is: 98
实际上,我们将 97 和 98 这两个数字进行比较。
Console.WriteLine("ab" > "aa") ' Prints True
假设我们有一个包含更多字符的字符串。 如果前几个字符相等,我们将比较下一个字符。 在我们的情况下,第二个位置的 b 字符的值比 a 字符大。 这就是为什么"ab"
字符串大于"aa"
字符串的原因。 当然,以这种方式比较字符串没有多大意义。 但这在技术上是可能的。
最后,我们将提到Is
运算符。 运算符检查两个对象引用是否引用同一对象。 它不执行值比较。
Option Strict On
Module Example
Sub Main()
Dim o1 As Object = New Object
Dim o2 As Object = New Object
Dim o3 As Object
o3 = o2
Console.WriteLine(o1 Is o2)
Console.WriteLine(o3 Is o2)
End Sub
End Module
我们创建三个对象,并将它们与Is
运算符进行比较。
Dim o1 As Object = New Object
Dim o2 As Object = New Object
我们声明并初始化两个Object
实例。 Object
类是.NET 框架中所有类的基类。 我们将在以后更详细地描述它。
Dim o3 As Object
仅声明第三个变量。
o3 = o2
o3
现在引用o2
对象。 它们是对同一对象的两个引用。
Console.WriteLine(o1 Is o2)
Console.WriteLine(o3 Is o2)
在第一种情况下,我们得到False
。 o1
和o2
是两个不同的对象。 在第二种情况下,我们得到True
。 o3
和o2
指的是同一对象。
按位运算符
小数对人类是自然的。 二进制数是计算机固有的。 二进制,八进制,十进制或十六进制符号仅是相同数字的符号。 按位运算符使用二进制数的位。 像 Visual Basic 这样的高级语言很少使用按位运算符。
符号 | 含义 |
---|---|
Not |
按位取反 |
Xor |
按位异或 |
And |
按位与 |
Or |
按位或 |
按位取反运算符分别将 1 更改为 0,将 0 更改为 1。
Console.WriteLine(Not 7) ' Prints -8
Console.WriteLine(Not -8) ' Prints 7
运算符恢复数字 7 的所有位。这些位之一还确定数字是否为负。 如果我们再一次对所有位取反,我们将再次得到 7。
按位,运算符在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时,位位置的结果才为 1。
00110
And 00011
= 00010
第一个数字是二进制符号 6,第二个数字是 3,结果是 2。
Console.WriteLine(6 And 3) ' Prints 2
Console.WriteLine(3 And 6) ' Prints 2
按位或运算符在两个数字之间进行逐位比较。 如果操作数中的任何对应位为 1,则位位置的结果为 1。
00110
Or 00011
= 00111
结果为00110
或十进制 7。
Console.WriteLine(6 Or 3) ' Prints 7
Console.WriteLine(3 Or 6) ' Prints 7
按位互斥或运算符在两个数字之间进行逐位比较。 如果操作数中对应位中的一个或另一个(但不是全部)为 1,则位位置的结果为 1。
00110
Xor 00011
= 00101
结果为00101
或十进制 5。
Console.WriteLine(6 Xor 3) ' Prints 5
复合赋值运算符
复合赋值运算符由两个运算符组成。 他们是速记员。
Option Strict On
Module Example
Dim a As Integer
Sub Main
a = 1
a = a + 1
Console.WriteLine(a) ' Prints 2
a += 1
Console.WriteLine(a) ' Prints 3
End Sub
End Module
+=
复合运算符是这些速记运算符之一。 它们比完整的表达式可读性差,但是经验丰富的程序员经常使用它们。
其他复合运算符是:
-= *= \= /= &= ^=
运算符优先级
运算符优先级告诉我们首先求值哪个运算符。 优先级对于避免表达式中的歧义是必要的。
以下表达式 28 或 40 的结果是什么?
3 + 5 * 5
像数学中一样,乘法运算符的优先级高于加法运算符。 结果是 28。
(3 + 5) * 5
要更改求值的顺序,可以使用括号。 括号内的表达式始终首先被求值。
下面的列表显示了按优先级排序的常见 Visual Basic 运算符(优先级最高):
运算符 | 描述 |
---|---|
^ |
求幂 |
+ - |
一元加减 |
* / |
乘法,浮点除法 |
\ |
整数除法 |
Mod |
模数 |
+ - |
加法,减法,字符串连接 |
& |
字符串连接 |
<< >> |
算术移位 |
= <> < > >= <= Is IsNot Like TypeOf Is |
所有比较运算符 |
Not |
否定 |
And AndAlso |
与 |
Or OrElse |
或 |
Xor |
异或 |
列表中同一行上的运算符具有相同的优先级。
Option Strict On
Module Example
Sub Main()
Console.WriteLine(3 + 5 * 5)
Console.WriteLine((3 + 5) * 5)
Console.WriteLine(Not True Or True)
Console.WriteLine(Not (True Or True))
End Sub
End Module
在此代码示例中,我们显示一些常见的表达式。 每个表达式的结果取决于优先级。
Console.WriteLine(3 + 5 * 5)
该行打印 28。乘法运算符的优先级高于加法。 首先计算5*5
的乘积。 然后添加 3。
Console.WriteLine(Not True Or True)
在这种情况下,否定运算符具有更高的优先级。 首先,第一个True
值被否定为False
,然后Or
运算符组合False
和True
,最后得到True
。
$ ./precedence.exe
28
40
True
False
关联性
有时,优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性确定优先级与相同的运算符的求值顺序。
9 / 3 * 3
这种表达的结果是什么? 9 还是 1? 乘法,删除和模运算符从左到右关联。 因此,该表达式的计算方式为:(9 / 3) * 3
,结果为 9。
算术,布尔,关系和按位运算符都是左右关联的。
另一方面,赋值运算符是正确关联的。
a = b = c = d = 0
Console.WriteLine("{0} {1} {2} {3}", a, b, c, d) ' Prints 0 0 0 0
如果关联从左到右,则以前的表达式将不可能。
复合赋值运算符从右到左关联。
j = 0
j *= 3 + 1
Console.WriteLine(j)
您可能期望结果为 1。但是实际结果为 0。由于有关联性。 首先求值右边的表达式,然后应用复合赋值运算符。
AddressOf
运算符
AddressOf
运算符创建一个指向另一个函数的函数委托。 委托是类型安全的函数指针,它们用于调用其他对象的方法。
Option Strict On
Module Example
Delegate Sub Display
Dim msg As New Display(AddressOf Message1)
Sub Main()
msg.Invoke()
msg = New Display(AddressOf Message2)
msg.Invoke()
End Sub
Sub Message1()
Console.WriteLine("This is message 1")
End Sub
Sub Message2()
Console.WriteLine("This is message 2")
End Sub
End Module
在代码示例中,我们使用AddressOf
运算符指向两个不同的子例程。
Delegate Sub Display
我们需要声明一个委托。
Dim msg As New Display(AddressOf Message1)
委托使用AddressOf
运算符获取子例程的地址。 现在,我们有一个指向Message1()
子例程的类型安全指针。
msg.Invoke()
Invoke()
方法调用委托指向的方法。
msg = New Display(AddressOf Message2)
msg.Invoke()
现在,我们为委托人提供另一个子例程的地址。
$ ./addressof.exe
This is message 1
This is message 2
两条消息都打印到控制台。
在 Visual Basic 教程的这一部分中,我们介绍了运算符。