# 运算符

> 原文： [https://zetcode.com/lang/visualbasic/operators/](https://zetcode.com/lang/visualbasic/operators/)

在 Visual Basic 教程的这一部分中，我们将讨论运算符。

运算符是特殊符号，表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。

我们有几种类型的运算符：

*   算术运算符
*   布尔运算符
*   关系运算符
*   按位运算符

一个运算符可以有一个或两个操作数。 操作数是运算符的输入（参数）之一。 仅使用一个操作数的那些运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。

```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

```

+和-可以是加减运算符，也可以是一元符号运算符。 这取决于实际情况。

```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

```

加号可以用来表示我们有一个正数。 但是它通常不被使用。 减号更改值的符号。

```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

```

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

## 赋值运算符

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

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

```

在这里，我们为`x`变量分配一个数字。

```vb
x = x + 1
Console.WriteLine(x)

```

先前的表达式在数学上没有意义。 但这在编程中是合法的。 该表达式将`x`变量加 1。 右边等于 2，并且 2 分配给`x`。

```vb
3 = x

```

此代码示例导致语法错误。 我们无法为文字分配值。

## 算术运算符

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

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

以下示例显示了算术运算。

```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

```

在前面的示例中，我们使用加，减，乘和除运算。 这些都是数学所熟悉的。

```vb
$ ./arithmetic.exe 
33
2
110
4

```

示例的输出。

接下来，我们将说明正态除法和整数除法之间的区别。

```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 有两个不同的除法运算符。

```vb
Dim a As Single = 5

```

我们使用浮点数据类型。

```vb
c = 5 / 2 
Console.WriteLine(c)

```

这是“正常”的分割操作。 它返回 2.5，如预期的那样。

```vb
c = 5 \ 2
Console.WriteLine(c)

```

这是整数除法。 此操作的结果始终为整数。 `c`变量的值为 2。

```vb
$ ./division.exe 
2.5
2

```

`division.exe`程序的结果。

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

```vb
Console.WriteLine(9 Mod 4) ' Prints 1

```

`Mod`运算符称为模运算符。 它找到一个数除以另一个的余数。 `9 Mod 4`，9 模 4 为 1，因为 4 两次乘以 9，余数为 1。例如，当我们要检查素数时，模运算符会很方便。

最后，我们将提到求幂运算符。

```vb
Console.WriteLine(9 ^ 2) ' Prints 81

```

9 ^ 2 = 9 * 9 = 81

## 连接字符串

在 Visual Basic 中，我们有两个用于字符串连接的运算符。 加号`+`运算符和`&`和号运算符。

```vb
Option Strict On

Module Example

    Sub Main()

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

    End Sub

End Module

```

我们使用两个运算符将三个字符串连接在一起。

```vb
$ ./concatstrings.exe 
Return of the king
Return of the king

```

这就是我们得到的。 两种情况的结果相同。

## 布尔运算符

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

| 符号 | 名称 |
| --- | --- |
| `And` | 逻辑与 |
| `AndAlso` | 短路与 |
| `Or` | 逻辑或 |
| `OrElse` | 短路或 |
| `Xor` | 逻辑异或 |
| `Not` | 否定 |

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

```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

```

许多表达式导致布尔值。 布尔值用于条件语句中。

```vb
Console.WriteLine(x = y) 
Console.WriteLine(y > x)

```

关系运算符始终导致布尔值。 这两行显示`False`和`True`。

```vb
If (y > x)
    Console.WriteLine("y is greater than x")
End If

```

仅在满足括号内的条件时才执行`If`语句的主体。 `x > y`返回`True`，因此消息“`y`大于`x`”被打印到终端。

```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`。

```vb
$ ./andop.exe 
True
False
False
False

```

如果正好一个操作数为`True`，则逻辑`Xor`运算符的计算结果为`True`。

```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`。

```vb
$ ./xorop.exe 
False
True
True
False

```

如果两个操作数中的任何一个为`True`，则逻辑`Or`运算符的计算结果为`True`。

```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。

```vb
$ ./orop.exe 
True
True
True
False

```

否定运算符`Not`设为`True False`和`False True`。

```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

```

该示例显示了否定运算符的作用。

```vb
$ ./negation.exe 
False
True
True

```

`AndAlso`和`OrElse`运算符经过短路求值。 短路求值意味着仅当第一个参数不足以确定表达式的值时才求值第二个参数：当`And`的第一个参数求值为`false`时，总值必须为`false`； 并且当`Or`的第一个参数计算为`true`时，总值必须为`true`。 （维基百科）短路求值主要用于提高性能。

一个例子可以使这一点更加清楚。

```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

```

在示例中，我们有两个功能。 函数与子例程不同，返回值。 这是它们之间的主要区别。

```vb
If (one AndAlso two)
    Console.WriteLine("Pass")
End If

```

一个函数返回`False`。 短路`AndAlso`不求值第二功能。 没有必要。 一旦操作数为`False`，逻辑结论的结果始终为`False`。 控制台上仅打印`"Inside one"`。

```vb
Console.WriteLine("#############")
If (one And two)
    Console.WriteLine("Pass")
End If

```

在第二种情况下，我们使用`And`。 在这种情况下，两个函数都被调用。 即使表达式的结果不是必需的。

```vb
$ ./shorcircuit.exe 
Short circuit
Inside one
#############
Inside one
Inside two

```

`shorcircuit.exe`程序的结果。

## 关系运算符

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

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

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

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

```

正如我们已经提到的，关系运算符返回布尔值。 请注意，在 Visual Basic 中，比较运算符为`=`。 不像受 C 和 C 影响的语言那样`==`。

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

```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

```

我们也可以比较字符串对象。 字符串上下文中的比较运算符比较字符的排序顺序。

```vb
Console.WriteLine("a" < "b") ' Prints True

```

这里到底发生了什么？ 计算机不知道字符或字符串。 对于他们来说，一切都只是数字。 字符是存储在特定表中的特殊数字。 类似于 ASCII。

```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 值。

```vb
$ ./compare.exe 
True
a is: 97
b is: 98

```

实际上，我们将 97 和 98 这两个数字进行比较。

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

```

假设我们有一个包含更多字符的字符串。 如果前几个字符相等，我们将比较下一个字符。 在我们的情况下，第二个位置的 b 字符的值比 a 字符大。 这就是为什么`"ab"`字符串大于`"aa"`字符串的原因。 当然，以这种方式比较字符串没有多大意义。 但这在技术上是可能的。

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

```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`运算符进行比较。

```vb
Dim o1 As Object = New Object
Dim o2 As Object = New Object

```

我们声明并初始化两个`Object`实例。 `Object`类是.NET 框架中所有类的基类。 我们将在以后更详细地描述它。

```vb
Dim o3 As Object 

```

仅声明第三个变量。

```vb
o3 = o2

```

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

```vb
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。

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

```

运算符恢复数字 7 的所有位。这些位之一还确定数字是否为负。 如果我们再一次对所有位取反，我们将再次得到 7。

按位，运算符在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时，位位置的结果才为 1。

```vb
      00110
  And 00011
   =  00010

```

第一个数字是二进制符号 6，第二个数字是 3，结果是 2。

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

```

按位或运算符在两个数字之间进行逐位比较。 如果操作数中的任何对应位为 1，则位位置的结果为 1。

```vb
     00110
  Or 00011
   = 00111

```

结果为`00110`或十进制 7。

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

```

按位互斥或运算符在两个数字之间进行逐位比较。 如果操作数中对应位中的一个或另一个（但不是全部）为 1，则位位置的结果为 1。

```vb
      00110
  Xor 00011
   =  00101

```

结果为`00101`或十进制 5。

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

```

## 复合赋值运算符

复合赋值运算符由两个运算符组成。 他们是速记员。

```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

```

`+=`复合运算符是这些速记运算符之一。 它们比完整的表达式可读性差，但是经验丰富的程序员经常使用它们。

其他复合运算符是：

```vb
-=   *=   \=   /=   &=  ^= 

```

## 运算符优先级

运算符优先级告诉我们首先求值哪个运算符。 优先级对于避免表达式中的歧义是必要的。

以下表达式 28 或 40 的结果是什么？

```vb
 3 + 5 * 5

```

像数学中一样，乘法运算符的优先级高于加法运算符。 结果是 28。

```vb
(3 + 5) * 5

```

要更改求值的顺序，可以使用括号。 括号内的表达式始终首先被求值。

下面的列表显示了按优先级排序的常见 Visual Basic 运算符（优先级最高）：

| 运算符 | 描述 |
| --- | --- |
| `^` | 求幂 |
| `+ -` | 一元加减 |
| `* /` | 乘法，浮点除法 |
| `\` | 整数除法 |
| `Mod` | 模数 |
| `+ -` | 加法，减法，字符串连接 |
| `&` | 字符串连接 |
| `<< >>` | 算术移位 |
| `= <> < > >= <= Is IsNot Like TypeOf Is` | 所有比较运算符 |
| `Not` | 否定 |
| `And AndAlso` | 与 |
| `Or OrElse` | 或 |
| `Xor` | 异或 |

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

```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

```

在此代码示例中，我们显示一些常见的表达式。 每个表达式的结果取决于优先级。

```vb
Console.WriteLine(3 + 5 * 5)

```

该行打印 28。乘法运算符的优先级高于加法。 首先计算`5*5`的乘积。 然后添加 3。

```vb
Console.WriteLine(Not True Or True)

```

在这种情况下，否定运算符具有更高的优先级。 首先，第一个`True`值被否定为`False`，然后`Or`运算符组合`False`和`True`，最后得到`True`。

```vb
$ ./precedence.exe 
28
40
True
False

```

## 关联性

有时，优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性确定优先级与相同的运算符的求值顺序。

```vb
9 / 3 * 3

```

这种表达的结果是什么？ 9 还是 1？ 乘法，删除和模运算符从左到右关联。 因此，该表达式的计算方式为：`(9 / 3) * 3`，结果为 9。

算术，布尔，关系和按位运算符都是左右关联的。

另一方面，赋值运算符是正确关联的。

```vb
a = b = c = d = 0
Console.WriteLine("{0} {1} {2} {3}", a, b, c, d) ' Prints 0 0 0 0 

```

如果关联从左到右，则以前的表达式将不可能。

复合赋值运算符从右到左关联。

```vb
j = 0
j *= 3 + 1
Console.WriteLine(j)  

```

您可能期望结果为 1。但是实际结果为 0。由于有关联性。 首先求值右边的表达式，然后应用复合赋值运算符。

## `AddressOf`运算符

`AddressOf`运算符创建一个指向另一个函数的函数委托。 委托是类型安全的函数指针，它们用于调用其他对象的方法。

```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`运算符指向两个不同的子例程。

```vb
Delegate Sub Display

```

我们需要声明一个委托。

```vb
Dim msg As New Display(AddressOf Message1)

```

委托使用`AddressOf`运算符获取子例程的地址。 现在，我们有一个指向`Message1()`子例程的类型安全指针。

```vb
msg.Invoke()

```

`Invoke()`方法调用委托指向的方法。

```vb
msg = New Display(AddressOf Message2)
msg.Invoke()

```

现在，我们为委托人提供另一个子例程的地址。

```vb
$ ./addressof.exe 
This is message 1
This is message 2

```

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

在 Visual Basic 教程的这一部分中，我们介绍了运算符。