ZetCode

Visual Basic 运算符

最后修改于 2023 年 10 月 18 日

在本 Visual Basic 教程中,我们将讨论运算符。

一个运算符是一个特殊的符号,它指示要执行某个过程。 编程语言中的运算符取自数学。 程序员使用数据。 运算符用于处理数据。

我们有几种类型的运算符

一个运算符可以有一个或两个操作数。 操作数是运算符的一个输入(参数)。 那些只使用一个操作数的运算符称为一元运算符。 那些使用两个操作数的被称为二元运算符

Program.vb
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

+ 和 - 符号既可以是加法和减法运算符,也可以是一元符号运算符。 这取决于具体情况。

Program.vb
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

加号可以用来表示我们有一个正数。 但它大多不使用。 减号改变一个值的符号。

Program.vb
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

乘法和加法运算符是二元运算符的例子。 它们与两个操作数一起使用。

赋值运算符

赋值运算符=将一个值赋给一个变量。 变量是值的占位符。 在数学中,=运算符具有不同的含义。 在一个等式中,=运算符是一个等式运算符。 等式的左边等于右边。

x = 1
Console.WriteLine(x) ' Prints 1

在这里,我们将一个数字赋给 x 变量。

x = x + 1
Console.WriteLine(x)

前面的表达式在数学上没有意义。但它在编程中是合法的。该表达式将 1 加到 x 变量。右边等于 2,并将 2 赋给 x

3 = x

此代码示例会导致语法错误。我们不能将值赋给字面量。

算术运算符

以下是 Visual Basic 中算术运算符的表格。

符号名称
+加法
-减法
*乘法
/除法
\整数除法
Mod模数
^求幂

下面的示例展示了算术运算。

Program.vb
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

在前面的例子中,我们使用加法、减法、乘法和除法运算。 这都来自数学。

$ dotnet run
33
2
110
4

接下来,我们展示普通除法和整数除法的区别。

Program.vb
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)

这是浮点除法。

c = 5 \ 2
Console.WriteLine(c)

这是整数除法。 这个操作的结果总是一个整数。

$ dotnet run
2.5
2

我们要提到的最后两个运算符是模数运算符和求幂运算符。

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 中,我们有两个用于字符串连接的运算符。 加号+运算符和&与号运算符。 我们也可以使用String.Concat方法。

Program.vb
Option Strict On

Module Example

    Sub Main()

        Console.WriteLine("Return " & "of " & "the king")
        Console.WriteLine("Return " + "of " + "the king")
        Console.WriteLine(String.Concat("Return ", "of ", "the king"))

    End Sub

End Module

我们连接三个字符串。

$ dotnet run
Return of the king
Return of the king
Return of the king

布尔运算符

在 Visual Basic 中,我们有以下逻辑运算符。 布尔运算符也称为逻辑运算符。

符号名称
And逻辑合取
AndAlso短路 And
Or逻辑包含
OrElse短路 Or
Xor逻辑包含
Not逻辑非

布尔运算符用于处理真值。

Program.vb
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”被打印到终端。

Program.vb
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。

$ dotnet run
True
False
False
False

逻辑Xor运算符计算为 True,如果只有一个操作数为 True。

Program.vb
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。

$ dotnet run
False
True
True
False

逻辑Or运算符计算为 True,如果其中一个操作数为 True。

Program.vb
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。

$ dotnet run
True
True
True
False

否定运算符Not将 True 变为 False,将 False 变为 True。

Program.vb
Option Strict On

Module Example

    Sub Main()

        Console.WriteLine(Not True)
        Console.WriteLine(Not False)
        Console.WriteLine(Not (4 < 3))

    End Sub

End Module

该示例展示了否定运算符的实际应用。

$ dotnet run
False
True
True

AndAlsoOrElse运算符是短路求值的。 短路求值意味着只有当第一个参数不足以确定表达式的值时,才会对第二个参数进行求值:当 And 的第一个参数计算为 false 时,总值必须为 false;当 Or 的第一个参数计算为 true 时,总值必须为 true。 短路求值主要用于提高性能。

一个例子可以更清楚地说明这一点。

Program.vb
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。 在这种情况下,两个函数都被调用。 即使这对表达式的结果来说是不必要的。

$ dotnet run
Short circuit
Inside one
#############
Inside one
Inside two

关系运算符

关系运算符用于比较值。这些运算符始终产生布尔值。

符号含义
<小于
<=小于或等于
>大于
>=大于或等于
=等于
<>不等于
Is比较引用

关系运算符也称为比较运算符。

Program.vb
Console.WriteLine(3 < 4) ' Prints True
Console.WriteLine(3 = 4) ' Prints False
Console.WriteLine(4 >= 3) ' Prints True

正如我们已经提到的,关系运算符返回布尔值。 请注意,在 Visual Basic 中,比较运算符是=

请注意,关系运算符不限于数字。 我们也可以将它们用于其他对象。 尽管它们可能并不总是有意义的。

Program.vb
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。

Program.vb
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 值。

$ dotnet run
True
a is: 97
b is: 98

实际上,我们比较两个数字,97 和 98。

Program.vb
Console.WriteLine("ab" > "aa") ' Prints True

假设我们有一个包含更多字符的字符串。 如果第一个字符相等,我们比较下一个字符。 在我们的例子中,第二个位置的 b 字符的值大于 a 字符。 这就是为什么“ab”字符串大于“aa”字符串。 当然,以这种方式比较字符串没有多大意义。 但从技术上讲,这是可行的。

最后,我们提到Is运算符。 该运算符检查两个对象引用是否引用同一对象。 它不执行值比较。

Program.vb
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 framework 中所有类的基类。 我们稍后会更详细地描述它。

Dim o3 As Object

第三个变量只是被声明了。

o3 = o2

o3现在引用o2对象。 它们是对同一对象的两个引用。

Console.WriteLine(o1 Is o2)
Console.WriteLine(o3 Is o2)

在第一种情况下,我们得到 False。 o1o2是两个不同的对象。 在第二种情况下,我们得到 True。 o3o2引用同一对象。

位运算符

十进制数对人类来说很自然。 二进制数对计算机来说是原生的。 二进制、八进制、十进制或十六进制符号只是同一数字的表示法。 位运算符处理二进制数字的位。 位运算符很少用于高级语言,如 Visual Basic。

符号含义
Not按位取反
Xor按位异或
And按位与
Or按位或

按位取反运算符 将每个 1 变为 0,将 0 变为 1。

Program.vb
Console.WriteLine(Not 7)  ' Prints -8
Console.WriteLine(Not -8) ' Prints 7

该运算符会翻转数字 7 的所有位。其中一位也决定了该数字是否为负数。如果我们再次对所有位进行取反,我们会得到数字 7。

按位与运算符对两个数字执行逐位比较。只有当操作数中对应的位都为 1 时,结果的该位才为 1。

      00110
  And 00011
   =  00010

第一个数字是 6 的二进制表示法,第二个是 3,结果是 2。

Program.vb
Console.WriteLine(6 And 3) ' Prints 2
Console.WriteLine(3 And 6) ' Prints 2

按位或运算符对两个数字执行逐位比较。当操作数中对应的位任一为 1 时,结果的该位为 1。

     00110
  Or 00011
   = 00111

结果是 00110 或十进制的 7。

Program.vb
Console.WriteLine(6 Or 3) ' Prints 7
Console.WriteLine(3 Or 6) ' Prints 7

按位异或运算符对两个数字执行逐位比较。当操作数中对应的位任一为 1 但不是两者都为 1 时,结果的该位为 1。

      00110
  Xor 00011
   =  00101

结果是 00101 或十进制的 5。

Program.vb
Console.WriteLine(6 Xor 3) ' Prints 5

复合赋值运算符

复合赋值运算符由两个运算符组成。它们是简写运算符。

Program.vb
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 异或

列表中同一行的运算符具有相同的优先级。

Program.vb
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。

$ dotnet run
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运算符创建一个指向另一个函数的函数委托。 委托是类型安全的函数指针,它们用于调用其他对象的方法。

Program.vb
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()

现在我们给委托另一个子例程的地址。

$ dotnet run
This is message 1
This is message 2

两条消息都打印到控制台。

在本 Visual Basic 教程中,我们介绍了运算符。