2. VB.NET语言基础
2.1. 简介
我们首先将 VB.NET 视为一种经典的编程语言。关于对象的内容将在后续章节中讨论。
在程序中包含两类内容
- 数据
- 操作数据的指令
通常,我们力求将数据与指令分离:
![]() |
2.2. VB.NET的数据
VB.NET 使用以下数据类型:
- 整数、实数和十进制数
- 字符和字符串
- 布尔值
- 日期
- 对象
2.2.1. 预定义的数据类型
类型 VB | 等效类型 .NET | 大小 | 值范围 |
布尔型 | System.Boolean | 2 字节 | True 或 False。 |
字节 | System.Byte | 1 字节 | 0 至 255(无符号)。 |
字符 | System.Char | 2 字节 | 0 至 65 535(无符号)。 |
日期 | System.DateTime | 8 字节 | 0001年1月1日0:00:00至9999年12月31日23:59:59。 |
十进制 | System.Decimal | 16 字节 | 0 至 +/-79 228 162 514 264 337 593 543 950 335(无小数);0 至 +/-7.9228162514264337593543950335(28 位小数); 最小的非零数为 +/-0.0000000000000000000000000001 (+/-1E-28)。 |
双精度 | System.Double | 8字节 | -1,79769313486231E+308 至 -4,94065645841247E-324 表示负值;4,94065645841247E-324 至 1,79769313486231E+308 表示正值。 |
整数 | System.Int32 | 4字节 | -2 147 483 648 至 2 147 483 647。 |
长整型 | System.Int64 | 8字节 | -9 223 372 036 854 775 808 至 9 223 372 036 854 775 807。 |
对象 | System.Object | 4字节 | 任何类型都可以存储在 Object 类型的变量中。 |
Short | System.Int16 | 2字节 | -32 768 至 32 767。 |
Single | System.Single | 4字节 | -3,402823E+38 至 -1,401298E-45 用于负值;1,401298E-45 至 3,402823E+38 用于正值。 |
字符串 | System.String(类) | 0 到约 20 亿个 Unicode 字符。 |
在上表中,我们可以发现 32 位整数有两种可能的类型:Integer 和 System.Int32。 这两种类型可以互换。其他类型 VB 及其在 .NET 平台中的等效类型也是如此。以下是一个程序示例:
Module types
Sub Main()
' 整数
Dim var1 As Integer = 100
Dim var2 As Long = 10000000000L
Dim var3 As Byte = 100
Dim var4 As Short = 4
' 实数
Dim var5 As Decimal = 4.56789D
Dim var6 As Double = 3.4
Dim var7 As Single = -0.000103F
' 日期
Dim var8 As Date = New Date(2003, 1, 1, 12, 8, 4)
' 布尔值
Dim var9 As Boolean = True
' 字符
Dim var10 As Char = "A"c
' 字符串
Dim var11 As String = "abcde"
' 对象
Dim var12 As Object = New Object
' 视图
Console.Out.WriteLine("var1=" + var1.ToString)
Console.Out.WriteLine("var2=" + var2.ToString)
Console.Out.WriteLine("var3=" + var3.ToString)
Console.Out.WriteLine("var4=" + var4.ToString)
Console.Out.WriteLine("var5=" + var5.ToString)
Console.Out.WriteLine("var6=" + var6.ToString)
Console.Out.WriteLine("var7=" + var7.ToString)
Console.Out.WriteLine("var8=" + var8.ToString)
Console.Out.WriteLine("var9=" + var9.ToString)
Console.Out.WriteLine("var10=" + var10)
Console.Out.WriteLine("var11=" + var11)
Console.Out.WriteLine("var12=" + var12.ToString)
End Sub
End Module
运行结果如下:
var1=100
var2=10000000000
var3=100
var4=4
var5=4,56789
var6=3,4
var7=-0,000103
var8=01/01/2003 12:08:04
var9=True
var10=A
var11=abcde
var12=System.Object
2.2.2. 字面数据的标记
145, -7, &FF (十六进制) | |
100000L | |
134.789, -45E-18 (-45 × 10⁻¹⁸) | |
134.789F, -45E-18F (-45 10-18) | |
100000D | |
"A"c | |
"今天" | |
true, false | |
New Date(2003, 1, 1) 表示 2003年1月1日 |
请注意以下几点:
- 100000L,字母 L 表示该数被视为长整型
- 134.789F,字母 F 表示将该数视为单精度实数
- 100000D,字母 D 表示将该数视为十进制实数
- "A"c,用于将字符串 "A" 转换为字符 'A'
- 字符串需用双引号 " " 包围。若字符串中需包含 " " 字符,则需将其重复一次,如 "abcd""e",以表示字符串 [abcd"e]。
2.2.3. 数据声明
2.2.3.1. 声明的作用
程序处理的数据由名称和类型来标识。这些数据存储在内存中。在程序编译时,编译器会根据程序员的声明,为每项数据分配一个由地址和大小标识的内存位置。 此外,这些声明还使编译器能够检测编程错误。例如,如果 x 是一个字符串,则运算 x=x*2 将被判定为错误。
2.2.3.2. 常量的声明
常量的声明语法如下:
const 标识符 as 类型=值
例如 [const PI as double=3.141592]。为何要声明常量?
- 如果为常量赋予一个有意义的名称,程序将更易于阅读:[const taux_tva as single=0.186F]
- 如果“常量”发生变化,修改程序也会更加容易。因此,在前面的例子中,如果增值税税率变为 33%,唯一需要修改的就是定义其值的语句:[const taux_tva as single=0.336F]。 如果程序中直接使用了0.186,那么就需要修改大量语句。
2.2.3.3. 变量声明
变量通过名称进行标识,并关联到一种数据类型。VB.NET 不区分大小写。因此,变量 FIN 和 fin 是相同的。变量可以在声明时进行初始化。声明一个或多个变量的语法为:
dim 变量1,变量2,...,变量n as 类型标识符
其中 identificateur_de_type 是一个预定义类型或由程序员定义的类型。
2.2.4. 数字与字符串之间的转换
nombre.ToString 或 "" & 数字 或 CType(数字,String) | |
objet.ToString | |
Integer.Parse(字符串) 或 Int32.Parse | |
Long.Parse(字符串)或 Int64.Parse | |
Double.Parse(字符串) | |
Single.Parse(字符串) |
如果字符串不代表一个有效的数字,则字符串到数字的转换可能会失败。 此时会引发一个名为 VB.NET 的致命错误(即异常)。可以通过以下 try/catch 子句来处理此错误:
try
appel de la fonction susceptible de générer l'exception
catch e as Exception
traiter l'exception e
end try
instruction suivante
如果函数未引发异常,则执行下一条指令;否则,进入子句 catch 的主体,然后执行下一条指令。 我们稍后将详细讨论异常处理。以下是一个展示数字与字符串之间主要转换技术的程序。在此示例中,函数将参数的值显示在屏幕上。因此,affiche(S) 会将 S 的值显示在屏幕上。
' 指令
Option Strict On
' 导入的命名空间
Imports System
' 测试模块
Module Module1
Sub Main()
' 主过程
' 局部数据
Dim S As String
Const i As Integer = 10
Const l As Long = 100000
Const f As Single = 45.78F
Dim d As Double = -14.98
' 数字 --> 字符串
affiche(CType(i, String))
affiche(CType(l, String))
affiche(CType(f, String))
affiche(CType(d, String))
'布尔值 --> 字符串
Const b As Boolean = False
affiche(b.ToString)
' 字符串 --> 整数
Dim i1 As Integer = Integer.Parse("10")
affiche(i1.ToString)
Try
i1 = Integer.Parse("10.67")
affiche(i1.ToString)
Catch e As Exception
affiche("Erreur [10.67] : " + e.Message)
End Try
' 字符串 --> 长整型
Dim l1 As Long = Long.Parse("100")
affiche("" + l1.ToString)
Try
l1 = Long.Parse("10.675")
affiche("" & l1)
Catch e As Exception
affiche("Erreur [10.675] : " + e.Message)
End Try
' 字符串 --> 双精度
Dim d1 As Double = Double.Parse("100,87")
affiche(d1.ToString)
Try
d1 = Double.Parse("abcd")
affiche("" & d1)
Catch e As Exception
affiche("Erreur [abcd] : " + e.Message)
End Try
' 字符串 --> 单精度
Dim f1 As Single = Single.Parse("100,87")
affiche(f1.ToString)
Try
d1 = Single.Parse("abcd")
affiche(f1.ToString)
Catch e As Exception
affiche("Erreur [abcd] : " + e.Message)
End Try
End Sub
' 显示
Public Sub affiche(ByVal S As String)
Console.Out.WriteLine("S=" + S)
End Sub
End Module
所得结果如下:
S=10
S=100000
S=45,78
S=-14,98
S=False
S=10
S=Erreur [10.67] : Le format de la chaîne d'entrée est incorrect.
S=100
S=Erreur [10.675] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.
需要注意的是,以字符串形式表示的实数必须使用逗号,而不是小数点。因此,应写为 Dim d As Double = -14.98,但 Dim d1 As Double = Double.Parse("100,87")
2.2.5. 数据数组
数组 VB.NET 是一种对象,用于将同类型的数据集合在同一个标识符下。其声明如下:
Dim Tableau(n) as type 或 Dim Tableau() as type = New type(n) {}
其中 n 是数组最后一个元素的索引。语法 Tableau(i) 表示编号为 i 的数据,其中 i 属于区间 [0,n]。 任何引用数据 Tableau(i) 的操作,若 i 不属于区间 [0,n],都将引发异常。数组可以在声明时同时进行初始化。 在这种情况下,无需指定最后一个元素的编号。
Dim entiers() As Integer = {0, 10, 20, 30}
数组有一个名为Length的属性,表示数组中的元素个数。以下是一个示例程序:
Module tab0
Sub Main()
' 第一个数组
Dim tab0(5) As Integer
For i As Integer = 0 To UBound(tab0)
tab0(i) = i
Next
For i As Integer = 0 To UBound(tab0)
Console.Out.WriteLine("tab0(" + i.ToString + ")=" + tab0(i).tostring)
Next
' 第二个数组
Dim tab1() As Integer = New Integer(5) {}
For i As Integer = 0 To tab1.Length - 1
tab1(i) = i * 10
Next
For i As Integer = 0 To tab1.Length - 1
Console.Out.WriteLine("tab1(" + i.ToString + ")=" + tab1(i).tostring)
Next
End Sub
End Module
及其运行结果:
tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50
一个二维数组可以声明如下:
Dim Tableau(n,m) as Type 或 Dim Tableau(,) as Type = New Type(n,m) {}
其中 n+1 表示行数,m+1 表示列数。语法 Tableau(i,j) 表示 Tableau 中第 i 行第 j 个元素。 二维数组也可以在声明时同时初始化:
Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}
每个维度的元素数量可通过方法 GetLenth(i) 获取,其中 i=0 表示对应第一个索引的维度,i=1 表示对应第二个索引的维度,……以下是一个示例程序:
Module Module2
Sub Main()
' 第一个表格
Dim tab0(2, 1) As Integer
For i As Integer = 0 To UBound(tab0)
For j As Integer = 0 To tab0.GetLength(1) - 1
tab0(i, j) = i * 10 + j
Next
Next
For i As Integer = 0 To UBound(tab0)
For j As Integer = 0 To tab0.GetLength(1) - 1
Console.Out.WriteLine("tab0(" + i.ToString + "," + j.ToString + ")=" + tab0(i, j).tostring)
Next
Next
' 第二个表格
Dim tab1(,) As Integer = New Integer(2, 1) {}
For i As Integer = 0 To tab1.GetLength(0) - 1
For j As Integer = 0 To tab1.GetLength(1) - 1
tab1(i, j) = i * 100 + j
Next
Next
For i As Integer = 0 To tab1.GetLength(0) - 1
For j As Integer = 0 To tab1.GetLength(1) - 1
Console.Out.WriteLine("tab1(" + i.ToString + "," + j.ToString + ")=" + tab1(i, j).tostring)
Next
Next
End Sub
End Module
及其执行结果:
tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50
数组的数组声明如下:
Dim Tableau(n)() as Type 或 Dim Tableau()() as Type = new Type(n)()
上述声明创建了一个包含 n+1 行 的数组。每个 Tableau(i) 元素都是一个一维数组的引用。上述声明时不会创建这些数组。以下示例演示了如何创建数组数组:
' 一个数组数组
Dim noms()() As String = New String(3)() {}
' 初始化
For i = 0 To noms.Length - 1
noms(i) = New String(i) {}
For j = 0 To noms(i).Length - 1
noms(i)(j) = "nom" & i & j
Next
Next
这里 noms(i) 是一个包含 i+1 个元素的数组。由于 noms(i) 是一个数组,因此 noms(i).Length 即为其元素个数。以下是一个将我们刚刚介绍的三种数组类型结合起来的示例:
' 指令
Option Strict On
Option Explicit On
' 导入
Imports System
' 测试类
Module test
Sub main()
' 一个已初始化的一维数组
Dim entiers() As Integer = {0, 10, 20, 30}
Dim i As Integer
For i = 0 To entiers.Length - 1
Console.Out.WriteLine("entiers[" & i & "]=" & entiers(i))
Next
' 一个已初始化的二维数组
Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}
Dim j As Integer
For i = 0 To réels.GetLength(0) - 1
For j = 0 To réels.GetLength(1) - 1
Console.Out.WriteLine("réels[" & i & "," & j & "]=" & réels(i, j))
Next
Next
' 数组数组
Dim noms()() As String = New String(3)() {}
' 初始化
For i = 0 To noms.Length°- 1
noms(i) =°New String(i) {}
For j = 0 To noms(i).Length - 1
noms(i)(j) = "nom" & i & j
Next
Next
' 显示
For i = 0 To noms.Length°- 1
For j = 0 To noms(i).Length - 1
Console.Out.WriteLine("noms[" & i & "][" & j & "]=" & noms(i)(j))
Next
Next
End Sub
End Module
运行后,我们得到以下结果:
entiers[0]=0
entiers[1]=10
entiers[2]=20
entiers[3]=30
réels[0,0]=0,5
réels[0,1]=1,7
réels[1,0]=8,4
réels[1,1]=-6
noms[0][0]=nom00
noms[1][0]=nom10
noms[1][1]=nom11
noms[2][0]=nom20
noms[2][1]=nom21
noms[2][2]=nom22
noms[3][0]=nom30
noms[3][1]=nom31
noms[3][2]=nom32
noms[3][3]=nom33
2.3. VB.NET的基本说明
区分
1 由计算机执行的基本指令。
2 控制程序运行的指令。
当我们考察微型计算机及其外围设备的结构时,基本指令便显而易见。
![]() |
-
读取来自键盘的信息
-
信息处理
-
将信息写入屏幕
-
从磁盘文件读取信息
-
将信息写入磁盘文件
2.3.1. 屏幕书写
屏幕上存在多种书写指令:
Console.Out.WriteLine(expression)
Console.WriteLine(expression)
Console.Error.WriteLine (expression)
其中 expression 代表任何可转换为字符串并在屏幕上显示的数据类型。在迄今为止的示例中,我们仅使用了 Console.Out.WriteLine(表达式) 语句。
类 System.Console 提供了屏幕写入操作(Write,WriteLine)。类 Console 具有两个属性 Out 和 Error,它们是类型为 StreamWriter 的写入流:
- Console.WriteLine() 与 Console.Out.WriteLine() 功能等同,并向通常与屏幕关联的 Out 流写入数据。
- Console.Error.WriteLine() 写入 Error 流,该流通常也关联到屏幕。
Out 和 Error 流默认关联到屏幕。但正如我们稍后将看到的,它们可以在程序运行时重定向到文本文件。
2.3.2. 读取键盘输入的数据
来自键盘的数据流由类型为 StreamReader 的对象 Console.In 表示。此类对象可通过 ReadLine 方法读取一行文本:
Dim ligne As String = Console.In.ReadLine()
键盘输入的行被存储在变量 ligne 中,随后可由 programme.Le 进行处理。In 流可像 Out 和 Error 流一样重定向到文件中。
2.3.3. 输入输出示例
以下是一个简短的程序,用于演示键盘/屏幕的输入输出操作:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
' 模块
Module io1
Sub Main()
' 写入 Out 流
Dim obj As New Object
Console.Out.WriteLine(("" & obj.ToString))
' 写入 Error 流
Dim i As Integer = 10
Console.Error.WriteLine(("i=" & i))
' 读取键盘输入的一行
Console.Out.Write("Tapez une ligne : ")
Dim ligne As String = Console.In.ReadLine()
Console.Out.WriteLine(("ligne=" + ligne))
End Sub
End Module
以及运行结果:
指令
Dim obj As New Object
Console.Out.WriteLine(obj.ToString)
仅用于说明任何对象均可被显示。本文不打算解释所显示内容的含义。
2.3.4. I/O重定向
在 DOS/Windows 系统中,有三个标准设备,分别称为:
- 标准输入设备——默认指键盘,编号为 0
- 标准输出设备——默认指向屏幕,编号为 1
- 标准错误设备——默认指向屏幕,编号为 2
在 VB.NET 中, 写入流 Console.Out 写入设备 1,写入流 Console.Error 写入设备 2,而读取流 Console.In 则从设备 0 读取数据。 在 Windows 的 DOS 窗口中运行程序时,可以指定该程序所使用的设备 0、1 和 2。请看以下命令行:
在程序 pg 的参数 argi 之后,可以将标准 I/O 设备重定向到文件:
标准输入流 0 被重定向到文件 in.txt。因此,在程序中,流 Console.In 将从文件 in.txt 中获取数据。 | ||||
将输出流 1 重定向至文件 out.txt。这导致在程序中,数据流 Console.Out 会将数据写入文件 out.txt | ||||
同上,但写入的数据将添加到文件 out.txt 的当前内容中。 | ||||
将输出流 2 重定向至文件 error.txt。这将导致程序中的数据流 Console.Error 将其数据写入文件 error.txt | ||||
同上,但写入的数据将追加到文件 error.txt 的现有内容中。 | ||||
设备 1 和 2 均被重定向到文件 | ||||
需要注意的是,为了将程序 pg 的 I/O 流重定向到文件,无需修改程序 pg。 OS 程序负责确定设备 0、1 和 2 的性质。请看以下程序:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
' 重定向
Module console2
Sub Main()
' 读取 In 流
Dim data As String = Console.In.ReadLine()
' 写入 Out 流
Console.Out.WriteLine(("écriture dans flux Out : " + data))
' 写入 Error 流
Console.Error.WriteLine(("écriture dans flux Error : " + data))
End Sub
End Module
编译该程序:
dos>vbc es2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.
dos>dir
24/02/2004 15:39 416 es2.vb
11/03/2004 08:20 3 584 es2.exe
让我们进行首次运行:
dos>es2.exe
un premier test
écriture dans flux Out : un premier test
écriture dans flux Error : un premier test
上一次执行并未重定向任何标准 I/O 流 In、Out 和 Error。现在我们将重定向这三个流。流 In 将被重定向到文件 in.txt, Out 流将重定向到文件 out.txt,Error 流将重定向到文件 error.txt。此重定向在命令行中以以下形式进行
执行后得到以下结果:
dos>more in.txt
un second test
dos>es2.exe 0<in.txt 1>out.txt 2>error.txt
dos>more out.txt
écriture dans flux Out : un second test
dos>more error.txt
écriture dans flux Error : un second test
可以清楚地看到,流程 Out 和 Error 写入的设备并不相同。
2.3.5. 将表达式的值赋给变量
这里我们关注的是变量=表达式这一操作。表达式可以是以下类型:算术、关系、布尔、字符。
2.3.5.1. 运算符列表
操作 | 语言元素 |
^, –, *, /, \, Mod, +, = | |
=, ^=, *=, /=, \=, +=, -=, &= | |
=, <>, <, >, <=, >=, Like, Is | |
&, + | |
非、与、或、异或、AndAlso、OrElse | |
AddressOf, GetType |
2.3.5.2. 算术表达式
算术表达式的运算符如下:
^, –, *, /, \, Mod, +, = |
+:加法,-:减法,*:乘法,/:实数除法,\:整数除法商,Mod:整数除法余数,^:幂运算。因此,以下程序:
' 算术运算符
Module operateursarithmetiques
Sub Main()
Dim i, j As Integer
i = 4 : j = 3
Console.Out.WriteLine(i & "/" & j & "=" & (i / j))
Console.Out.WriteLine(i & "\" & j & "=" & (i \ j))
Console.Out.WriteLine(i & " mod " & j & "=" & (i Mod j))
Dim r1, r2 As Double
r1 = 4.1 : r2 = 3.6
Console.Out.WriteLine(r1 & "/" & r2 & "=" & (r1 / r2))
Console.Out.WriteLine(r1 & "^2=" & (r1 ^ 2))
Console.Out.WriteLine(Math.Cos(3))
End Sub
End Module
将产生以下结果:
数学函数种类繁多。以下列举其中几种:
| 平方根 |
| 余弦 |
| 正弦 |
| 正切 |
| x的y次方 (x>0) |
| 指数函数 |
| 自然对数 |
| 绝对值 |
所有这些函数都定义在一个名为 Math 的类中。使用时,必须在函数名前加上其所属类的名称。因此,应写为:
类 Math 的完整定义如下:
表示由常数 e 指定的自然对数底。 | ||||
表示圆周长与直径之比,由常数 π 指定。 | ||||
重载。返回指定数字的绝对值。 | ||||
返回其余弦值为指定数的角。 | ||||
返回正弦值为指定数的角。 | ||||
返回正切值为指定数值的角。 | ||||
返回正切值为两个指定数字之商的角度。 | ||||
计算两个 32 位数的整数乘积。 | ||||
返回不小于指定数的最小整数。 | ||||
返回指定角度的余弦值。 | ||||
返回指定角度的双曲余弦值。 | ||||
重载。返回两个数的商,并将余数作为输出参数返回。 | ||||
返回 e 的指定次幂。 | ||||
返回不大于指定数的最大整数。 | ||||
返回指定数除以另一个数的余数。 | ||||
已重载。返回指定数的对数。 | ||||
返回指定数的十进制对数。 | ||||
重载。返回两个指定数字中的较大者。 | ||||
重载。返回两个数中的较小值。 | ||||
返回指定数字的指定次方。 | ||||
重载。返回最接近指定值的数字。 | ||||
重载。返回一个表示数字符号的值。 | ||||
返回指定角度的正弦值。 | ||||
返回指定角度的双曲正弦值。 | ||||
返回指定数的平方根。 | ||||
返回指定角度的正切值。 | ||||
返回指定角度的双曲正切值。 | ||||
当一个函数被声明为“重载”时,意味着它针对不同类型的参数存在。例如,函数 Abs(x) 针对 x 的 Integer、Long、Decimal、Single 和 Float 类型分别存在。对于每种类型,都有一个独立的 Abs 函数定义。因此,我们说该函数是重载的。
2.3.5.3. 算术表达式求值中的优先级
在求算算术表达式时,运算符的优先级如下(从最高优先级到最低优先级):
类别 | 运算符 |
所有不含运算符的表达式:函数、括号 | |
^ | |
+, - | |
*, / | |
\ | |
Mod | |
+, - |
2.3.5.4. 关系运算符
运算符如下:
=, <>, <, >, <=, >=, Like, Is |
=:等于,<>:不等于,<:小于(严格),>:大于(严格),<=:小于或等于,>=:大于或等于,Like:符合模式,Is:对象相等。所有这些运算符具有相同的优先级。它们从左到右进行求值。关系表达式的结果为布尔值。
字符串比较:考虑以下程序:
' 命名空间
Imports System
Module string1
Sub main()
Dim ch1 As Char = "A"c
Dim ch2 As Char = "B"c
Dim ch3 As Char = "a"c
Console.Out.WriteLine("A<B=" & (ch1 < ch2))
Console.Out.WriteLine("A<a=" & (ch1 < ch3))
Dim chat As String = "chat"
Dim chien As String = "chien"
Dim chaton As String = "chaton"
Dim chat2 As String = "CHAT"
Console.Out.WriteLine("chat<chien=" & (chat < chien))
Console.Out.WriteLine("chat<chaton=" & (chat < chaton))
Console.Out.WriteLine("chat<CHAT=" & (chat < chat2))
Console.Out.WriteLine("chaton like chat*=" & ("chaton" Like "chat*"))
End Sub
End Module
及其执行结果:
假设有两个字符 C1 和 C2。可以使用以下运算符对它们进行比较:<、<=、=、<>、>、>=。此时比较的是它们的 Unicode 字符值,即数字。 根据Unicode排序规则,它们之间的关系如下:
空格 < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'
字符串按字符逐个比较。两个字符之间遇到的第一个不等关系,将导致字符串之间产生同向的不等关系。基于上述说明,请读者研究前一个程序的运行结果。
2.3.5.5. 布尔表达式
运算符如下:
Not、And、Or、Xor、AndAlso、OrElse |
Not:逻辑与,Or:逻辑或,Not:否定,Xor:异或。
op1 AndAlso op2:如果 op1 为假,则不计算 op2,结果为假。
op1 OrElse op2:如果 op1 为真,则不计算 op2,结果为真。
这些运算符之间的优先级如下:
非 | |
And, AndAlso | |
或者,OrElse | |
异或 |
布尔表达式的结果是一个布尔值。
2.3.5.6. 位运算
一方面,这里包含与布尔运算符相同的运算符,且优先级相同。此外还有两个移位运算符:<< 和 >>。设 i 和 j 为两个整数。
将 i 向左移 n 位。新移入的位均为零。 | |
将 i 向右移位 n 位。如果 i 是带符号整数(signed char、int、long),则保留符号位。 | |
对 i 和 j 进行位与运算。 | |
执行 i 与 j 的按位逻辑或运算。 | |
将 i 补为 1 | |
对 i 和 j 执行 OU EXCLUSIF 运算 |
假设以下程序:
Module operationsbit
Sub main()
' 位操作
Dim i As Short = &H123F
Dim k As Short = &H7123
Console.Out.WriteLine("i<<4=" & (i << 4).ToString("X"))
Console.Out.WriteLine("i>>4=" & (i >> 4).ToString("X"))
Console.Out.WriteLine("k>>4=" & (k >> 4).ToString("X"))
Console.Out.WriteLine("i and 4=" & (i And 4).ToString("X"))
Console.Out.WriteLine("i or 4 =" & (i Or 4).ToString("X"))
Console.Out.WriteLine("not i=" & (Not i).ToString("X"))
End Sub
End Module
其执行结果如下:
2.3.5.7. 与赋值相关的运算符
可以写成 a+=b,其含义为 a=a+b。可与赋值运算结合使用的运算符列表如下:
^=, *=, /=, \=, +=, -=, &= |
2.3.5.8. 运算符的一般优先级
类别 | 操作员 |
所有不含运算符的表达式 | |
^ | |
+, - | |
*, / | |
\ | |
Mod | |
+, - | |
& | |
<<, >> | |
=, <>, <, >, <=, >=, Like, Is, TypeOf...Is | |
Not | |
And, AndAlso | |
或者,OrElse | |
异或 |
当一个操作数位于两个优先级相同的运算符之间时,运算符的结合律决定了运算的执行顺序。所有运算符均为左结合,这意味着运算从左到右执行。优先级和结合律可以通过括号中的表达式来控制。
2.3.5.9. 类型转换
存在一些预定义函数,可用于将一种数据类型转换为另一种。其列表如下:
这些函数接受数值表达式或字符串作为参数。结果的类型如下表所示:
函数 | 结果 | 函数参数的取值范围 |
布尔型 | 任何有效的字符串或数字表达式。 | |
字节 | 0 至 255;小数部分将四舍五入。 | |
字符 | 任何有效的字符串表达式;值可在 0 到 65 535 之间。 | |
日期 | 任何有效的日期和时间表示形式。 | |
Double | -1,79769313486231E+308 至 -4,94065645841247E-324 表示负值;4,94065645841247E-324 至 1,79769313486231E+308 表示正值。 | |
十进制 | +/-79 228 162 514 264 337 593 543 950 335(无小数部分的数值)。28位小数的数值范围为 +/-7.9228162514264337593543950335。最小的非零数是 0.0000000000000000000000000001。 | |
整数 | -2 147 483 648 到 2 147 483 647;小数部分被四舍五入。 | |
长整型 | -9 223 372 036 854 775 808 至 9 223 372 036 854 775 807;小数部分四舍五入。 | |
| 对象 | 任何有效的表达式。 |
Short | -32 768 至 32 767;小数部分四舍五入。 | |
单精度 | 对于负值,范围为 -3,402823E 至 -1,401298E-45;对于正值,范围为 1,401298E-45 至 3,402823E+38。 | |
字符串 | Cstr 函数返回的值取决于表达式参数。 |
以下是一个示例程序:
Module conversion
Sub main()
Dim var1 As Boolean = CBool("true")
Dim var2 As Byte = CByte("100")
Dim var3 As Char = CChar("A")
Dim var4 As Date = CDate("30 janvier 2004")
Dim var5 As Double = CDbl("100,45")
Dim var6 As Decimal = CDec("1000,67")
Dim var7 As Integer = CInt("-30")
Dim var8 As Long = CLng("456")
Dim var9 As Short = CShort("-14")
Dim var10 As Single = CSng("56,78")
Console.Out.WriteLine("var1=" & var1)
Console.Out.WriteLine("var2=" & var2)
Console.Out.WriteLine("var3=" & var3)
Console.Out.WriteLine("var4=" & var4)
Console.Out.WriteLine("var5=" & var5)
Console.Out.WriteLine("var6=" & var6)
Console.Out.WriteLine("var7=" & var7)
Console.Out.WriteLine("var8=" & var8)
Console.Out.WriteLine("var9=" & var9)
Console.Out.WriteLine("var10=" & var10)
End Sub
End Module
及其执行结果:
var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78
也可以使用函数 CType(expression, type),如下面的程序所示:
Module ctype1
Sub main()
Dim var1 As Boolean = CType("true", Boolean)
Dim var2 As Byte = CType("100", Byte)
Dim var3 As Char = CType("A", Char)
Dim var4 As Date = CType("30 janvier 2004", Date)
Dim var5 As Double = CType("100,45", Double)
Dim var6 As Decimal = CType("1000,67", Decimal)
Dim var7 As Integer = CType("-30", Integer)
Dim var8 As Long = CType("456", Long)
Dim var9 As Short = CType("-14", Short)
Dim var10 As Single = CType("56,78", Single)
Dim var11 As String = CType("47,89", String)
Dim var12 As String = 47.89.ToString
Dim var13 As String = "" & 47.89
Console.Out.WriteLine("var1=" & var1)
Console.Out.WriteLine("var2=" & var2)
Console.Out.WriteLine("var3=" & var3)
Console.Out.WriteLine("var4=" & var4)
Console.Out.WriteLine("var5=" & var5)
Console.Out.WriteLine("var6=" & var6)
Console.Out.WriteLine("var7=" & var7)
Console.Out.WriteLine("var8=" & var8)
Console.Out.WriteLine("var9=" & var9)
Console.Out.WriteLine("var10=" & var10)
Console.Out.WriteLine("var11=" & var11)
Console.Out.WriteLine("var12=" & var12)
Console.Out.WriteLine("var13=" & var13)
End Sub
End Module
该程序将产生以下结果:
var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78
var11=47,89
var12=47,89
var13=47,89
2.4. 程序执行控制指令
2.4.1. 停止
在类 Environment 中定义的方法 Exit 可用于停止程序的执行:
[Visual Basic]
Public Shared Sub Exit(ByVal exitCode As Integer )
将终止当前进程,并向父进程返回值 exitCode。父进程可使用 exitCode 的值。 在 DOS 环境下,该状态变量会被返回为 DOS,并存储在系统变量 ERRORLEVEL 中,该值可在批处理文件中进行检测。 在 Unix 系统中,变量 $? 用于获取 exitCode 的值。
将以状态值为 0 终止程序的执行。
2.4.2. 简单选择结构
- 每项操作占一行
- else子句可以省略。
可以选择结构进行嵌套,如下例所示:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module if1
Sub main()
Dim i As Integer = 10
If i > 4 Then
Console.Out.WriteLine(i & " est > " & 4)
Else
If i = 4 Then
Console.Out.WriteLine(i & " est = " & 4)
Else
Console.Out.WriteLine(i & " est < " & 4)
End If
End If
End Sub
End Module
所得结果:
2.4.3. 案例结构
语法如下:
select case expression
case liste_valeurs1
actions1
case liste_valeurs2
actions2
...
case else
actions_sinon
end select
- [expression] 的类型必须是以下类型之一:
- [case else]子句可以省略。
- [liste_valeursi] 是该表达式的可能取值。[listes_valeursi] 表示条件列表 condition1, condition2, ..., conditionx。 如果 [expression] 验证了其中一个条件,则执行 [liste_valeursi] 子句后面的操作。条件可以采用以下形式:
- val1 to val2:若 [expression] 属于 [val1,val2] 域,则为真
- val1:若 [expression] 等于 val1,则为真
- is > val1:若 [expression] > val1 则为真。关键字 [is] 可以省略
- 运算符 =、<、<=、>、>=、<> 亦同
- 仅执行与第一个满足条件相关的操作。
考虑以下程序:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module selectcase1
Sub main()
Dim i As Integer = 10
Select Case i
Case 1 To 4, 7 To 8
Console.Out.WriteLine("i est dans l'intervalle [1,4] ou [7,8]")
Case Is > 12
Console.Out.WriteLine("i est > 12")
Case Is < 15
Console.Out.WriteLine("i est < 15")
Case Is < 20
Console.Out.WriteLine("i est < 20")
End Select
End Sub
End Module
它产生以下结果:
2.4.4. 重复结构
2.4.4.1. 已知重复次数
For counter [ As datatype ] = start To end [ Step step ]
actions
Next [ counter ]
对于变量 [counter] 所取的每个值,都会执行相应的操作。请看以下程序:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module for1
Sub main()
Dim somme As Integer = 0
Dim résultat As String = "somme("
For i As Integer = 0 To 10 Step 2
somme += i
résultat += " " + i.ToString
Next
résultat += ")=" + somme.ToString
Console.Out.WriteLine(résultat)
End Sub
End Module
结果:
另一种迭代次数已知的迭代结构如下:
For Each element [ As datatype ] In groupe
[ actions ]
Next [ element ]
- groupe 是一个对象集合。我们已经知道的对象集合是数组
- datatype 是集合中对象的类型。对于数组而言,这相当于数组元素的类型
- element 是循环的局部变量,它将依次取集合中的所有值作为其值。
因此,以下代码:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module foreach1
Sub main()
Dim amis() As String = {"paul", "hélène", "jacques", "sylvie"}
For Each nom As String In amis
Console.Out.WriteLine(nom)
Next
End Sub
End Module
将显示:
2.4.4.2. 重复次数未知
对于这种情况,VB.NET中存在许多结构。
Do { While | Until } condition
[ statements ]
Loop
循环将持续执行,直到条件为真(while)或直到条件为真(until)。该循环可能永远不会被执行。
Do
[ statements ]
Loop { While | Until } condition
循环将持续执行,直到条件为真(while)或直到条件为真(until)。循环至少会执行一次。
While condition
[ statements ]
End While
只要条件成立,循环就继续。该循环可能永远不会被执行。以下循环均计算前10个整数的和。
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module boucles1
Sub main()
Dim i, somme As Integer
i = 0 : somme = 0
Do While i < 11
somme += i
i += 1
Loop
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do Until i = 11
somme += i
i += 1
Loop
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do
somme += i
i += 1
Loop Until i = 11
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do
somme += i
i += 1
Loop While i < 11
Console.Out.WriteLine("somme=" + somme.ToString)
End Sub
End Module
2.4.4.3. 循环管理说明
退出 do ... loop 循环 | |
退出 for 循环 |
2.5. 程序结构 VB.NET
一个不使用用户定义类,且除主函数 Main 以外不使用其他函数的程序 VB.NET,其结构可能如下:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports espace1
Imports ....
Module nomDuModule
Sub main()
....
End Sub
End Module
- 指令 [Option Explicit on] 强制要求声明变量。在 VB.NET 中,变量声明并非强制要求。未声明的变量将被视为 Object 类型。
- 指令 [Option Strict on] 禁止任何可能导致数据丢失的数据类型转换,以及数值类型与字符串之间的转换。此时必须显式使用转换函数。
- 程序会导入其所需的所有命名空间。我们尚未引入这一概念。在之前的程序中,我们经常遇到如下语句:
实际上,我们本应这样写:
其中 System 是包含类 [Console] 的命名空间。 通过 Imports 语句导入命名空间 [System] 后,当 VB.NET 遇到未知类时,它会系统地遍历该命名空间。它将遍历所有已声明的命名空间,直到找到目标类为止。因此,我们应写为:
' 命名空间
Imports System
....
Console.Out.WriteLine(unechaine)
程序示例如下:
' 选项
Option Explicit On
Option Strict On
'命名空间
Imports System
' 主模块
Module main1
Sub main()
Console.Out.WriteLine("main1")
End Sub
End Module
该程序也可以如下编写:
' 选项
Option Explicit On
Option Strict On
'命名空间
Imports System
' 测试类
Public Class main2
Public Shared Sub main()
Console.Out.WriteLine("main2")
End Sub
End Class
这里我们使用了将在下一章介绍的类概念。当此类包含一个名为 main 的静态(shared)过程时,该过程将被执行。 我们在此引入这种写法,是因为VB.NET的姊妹语言C#只认识类概念,即c.a.d,且所有执行的代码都必须属于某个类。 类这一概念属于面向对象编程范畴。将其强加于所有程序的设计中略显笨拙。这在前文程序的第2版中可见一斑,其中我们在本无需使用类和静态方法的地方引入了这些概念。因此,今后我们仅在必要时才引入类这一概念。 在其他情况下,我们将像上文第1版那样使用模块的概念。
2.6. 编译并运行程序 VB.NET
编译程序 VB.NET 仅需 SDK.NET。请看以下程序:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module boucles1
Sub main()
Dim i, somme As Integer
i = 0 : somme = 0
Do While i < 11
somme += i
i += 1
Loop
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do Until i = 11
somme += i
i += 1
Loop
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do
somme += i
i += 1
Loop Until i = 11
Console.Out.WriteLine("somme=" + somme.ToString)
i = 0 : somme = 0
Do
somme += i
i += 1
Loop While i < 11
Console.Out.WriteLine("somme=" + somme.ToString)
End Sub
End Module
假设该程序位于名为 [boucles1.vb] 的文件中。要编译它,请按以下步骤操作:
dos>dir boucles1.vb
11/03/2004 15:55 583 boucles1.vb
dos>vbc boucles1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.
dos>dir boucles1.*
11/03/2004 16:04 601 boucles1.vb
11/03/2004 16:04 3 584 boucles1.exe
程序 vbc.exe 是编译器 VB.NET。在此,它位于 PATH 的 DOS 中:
dos>path
PATH=E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;E:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;E:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;E:\WINNT\Microsoft.NET\Framework\v1.1.4322;e:\winnt\system32;e:\winnt;
dos>dir E:\WINNT\Microsoft.NET\Framework\v1.1.4322\vbc.exe
21/02/2003 10:20 737 280 vbc.exe
编译器 [vbc] 生成一个可由虚拟机执行的 .exe 文件 .NET:
2.7. 示例 IMPOTS
我们打算编写一个程序来计算纳税人的税款。我们假设一种简化情况,即纳税人只有工资需要申报:
- 计算该雇员的税额份额 nbParts=nbEnfants/2 +1(若未婚), 已婚者为 nbEnfants/2+2,其中 nbEnfants 代表其子女数。
- 若其子女数≥3,则额外增加半份
- 计算其应税收入 R=0.72*S,其中 S 为其年薪
- 计算其家庭系数 QF=R/nbParts
- 计算其应纳税额 I。请看下表:
12620.0 | 0 | 0 |
13190 | 0.05 | 631 |
15640 | 0.1 | 1290.5 |
24740 | 0.15 | 2072.5 |
31810 | 0.2 | 3309.5 |
39970 | 0.25 | 4900 |
48360 | 0.3 | 6898.5 |
55790 | 0.35 | 9316.5 |
92970 | 0.4 | 12106 |
127860 | 0.45 | 16754.5 |
151250 | 0.50 | 23147.5 |
172040 | 0.55 | 30710 |
195000 | 0.60 | 39312 |
0 | 0.65 | 49062 |
每行有 3 个字段。要计算税款 I,需查找满足 QF<=字段1 的第一行。例如,若 QF=23000,则会找到该行
此时税额 I 等于 0.15*R - 2072.5*nbParts。 如果 QF 使得关系 QF<=field1 从未成立,则使用最后一行中的系数。此处:
由此得出税额 I=0.65*R - 49062*nbParts。相应的程序 VB.NET 如下:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module impots
' ------------ 主
Sub Main()
' 计算税款所需的数据表
Dim Limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Dim CoeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' 获取婚姻状况
Dim OK As Boolean = False
Dim reponse As String = Nothing
While Not OK
Console.Out.Write("Etes-vous marié(e) (O/N) ? ")
reponse = Console.In.ReadLine().Trim().ToLower()
If reponse <> "o" And reponse <> "n" Then
Console.Error.WriteLine("Réponse incorrecte. Recommencez")
Else
OK = True
End If
End While
Dim Marie As Boolean = reponse = "o"
' 子女人数
OK = False
Dim NbEnfants As Integer = 0
While Not OK
Console.Out.Write("Nombre d'enfants : ")
reponse = Console.In.ReadLine()
Try
NbEnfants = Integer.Parse(reponse)
If NbEnfants >= 0 Then
OK = True
Else
Console.Error.WriteLine("Réponse incorrecte. Recommencez")
End If
Catch
Console.Error.WriteLine("Réponse incorrecte. Recommencez")
End Try
End While
' 工资
OK = False
Dim Salaire As Integer = 0
While Not OK
Console.Out.Write("Salaire annuel : ")
reponse = Console.In.ReadLine()
Try
Salaire = Integer.Parse(reponse)
If Salaire >= 0 Then
OK = True
Else
Console.Error.WriteLine("Réponse incorrecte. Recommencez")
End If
Catch
Console.Error.WriteLine("Réponse incorrecte. Recommencez")
End Try
End While
' 计算份额数
Dim NbParts As Decimal
If Marie Then
NbParts = CDec(NbEnfants) / 2 + 2
Else
NbParts = CDec(NbEnfants) / 2 + 1
End If
If NbEnfants >= 3 Then
NbParts += 0.5D
End If
' 应税收入
Dim Revenu As Decimal
Revenu = 0.72D * Salaire
' 家庭分摊系数
Dim QF As Decimal
QF = Revenu / NbParts
' 查找与 QF 对应的税率档位
Dim i As Integer
Dim NbTranches As Integer = Limites.Length
Limites((NbTranches - 1)) = QF
i = 0
While QF > Limites(i)
i += 1
End While
' 税额
Dim impots As Integer = CInt(i * 0.05D * Revenu - CoeffN(i) * NbParts)
' 显示结果
Console.Out.WriteLine(("Impôt à payer : " & impots))
End Sub
End Module
该程序在 DOS 窗口中通过以下命令编译:
dos>vbc impots1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir impots1.exe
24/02/2004 15:42 5 632 impots1.exe
编译后生成可执行文件 impots.exe。 需要注意的是,impots.exe 无法被处理器直接执行。它实际上包含中间代码,该代码仅能在 .NET 平台上执行。所得结果如下:
dos>impots1
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
dos>impots1
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
dos>impots1
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0
2.8. 主程序的参数
主程序 Main 可以接受一个字符串数组作为参数:
Sub main(ByVal args() As String)
参数 args 是一个字符串数组,用于接收调用程序时通过命令行传递的参数。
- args.Length 是数组的元素个数args
- args(i) 是数组的第 i 个元素
如果使用以下命令启动程序 P: P arg0 arg1 … argn,且程序 P 中的过程 Main 声明如下:
Sub main(ByVal args() As String)
则 arg(0)="arg0", arg(1)="arg1" … 以下是一个示例:
' 说明
Option Strict On
Option Explicit On
' 命名空间
Imports System
Module arg
Sub main(ByVal args() As String)
' 参数个数
console.out.writeline("Il y a " & args.length & " arguments")
Dim i As Integer
For i = 0 To args.Length - 1
Console.Out.WriteLine("argument n° " & i & "=" & args(i))
Next
End Sub
End Module
执行结果如下:
2.9. 枚举
枚举是一种数据类型,其取值范围是一组整数常量。假设有一个程序需要处理考试成绩。共有五种成绩:及格、AssezBien、良好、TrèsBien、优秀。因此,我们可以为这五个常量定义一个枚举:
Enum mention
Passable
AssezBien
Bien
TrésBien
Excellent
End Enum
在内部,这五个常量由连续的整数编码,第一个常量从 0 开始,第二个从 1 开始,依此类推。可以声明一个变量来取枚举中的这些值:
' 从枚举中获取值的变量
Dim maMention As mention = mention.Passable
可以将变量与枚举中的各种可能值进行比较:
' 使用枚举值进行测试
If (maMention = mention.Passable) Then
Console.Out.WriteLine("Peut mieux faire")
End If
可以获取枚举的所有值:
For Each m In mention.GetValues(maMention.GetType)
Console.Out.WriteLine(m)
Next
正如简单类型 Integer 等同于结构 Int32 一样,简单类型 Enum 也等同于结构 Enum。 该类有一个静态方法 GetValues,用于获取作为参数传递的枚举类型的所有值。该参数必须是 Type 类型的对象,Type 是一个关于数据类型的信息类。 变量 v 的类型可通过 v.GetType() 获取。 因此,此处 maMention.GetType() 返回枚举 mentions 的对象 Type,而 Enum.GetValues(maMention.GetType())则返回枚举 mentions 的值列表。
如下面的程序所示:
' 指令
Option Strict On
Option Explicit On
' 命名空间
Imports System
Public Module enum2
' 一个枚举
Enum mention
Passable
AssezBien
Bien
TrèsBien
Excellent
End Enum
' 测试页面
Sub Main()
' 一个从枚举中获取值的变量
Dim maMention As mention = mention.Passable
' 显示变量值
Console.Out.WriteLine("mention=" & maMention)
' 使用枚举值的测试
If (maMention = mention.Passable) Then
Console.Out.WriteLine("Peut mieux faire")
End If
' 字面量列表
For Each m As mention In [Enum].GetValues(maMention.GetType)
Console.Out.WriteLine(m.ToString)
Next
' 完整标记列表
For Each m As Integer In [Enum].GetValues(maMention.GetType)
Console.Out.WriteLine(m)
Next
End Sub
End Module
运行结果如下:
dos>enum2
mention=0
Peut mieux faire
Passable
AssezBien
Bien
TrèsBien
Excellent
0
1
2
3
4
2.10. 异常处理
许多 VB.NET 函数可能会引发异常,即错误。当某个函数可能引发异常时,程序员应进行异常处理,以使程序更具容错性:必须始终避免应用程序发生“无预兆的崩溃”。
异常处理遵循以下流程:
try
appel de la fonction susceptible de générer l'exception
catch e as Exception e)
traiter l'exception e
end try
instruction suivante
如果该函数未抛出异常,则跳转至下一条指令;否则,进入子句 catch 的主体,然后跳转至下一条指令。请注意以下几点:
- e 是 Exception 类型的派生对象。通过使用 IOException、SystemException 等类型可以更精确地指定:存在多种类型的异常。 编写 catch e as Exception 表示希望处理所有类型的异常。如果 try 子句的代码可能引发多种类型的异常,则可以通过使用多个 catch 子句来更精确地处理异常:
try
appel de la fonction susceptible de générer l'exception
catch e as IOException
traiter l'exception e
catch e as SystemException
traiter l'exception e
end try
instruction suivante
- 可以在 try/catch 子句中添加一个 finally 子句:
try
appel de la fonction susceptible de générer l'exception
catch e as Exception
traiter l'exception e
finally
code exécuté après try ou catch
end try
instruction suivante
无论是否发生异常,子句 finally 的代码都会被执行。
- 在子句 catch 中,可能不希望使用可用的对象 Exception。因此,与其编写 catch e as Exception,不如直接编写 catch。
- 类 Exception 具有一个名为 Message 的属性,该属性包含详细描述所发生错误的消息。因此,若要显示该消息,应编写如下代码:
catch e as Exception
Console.Error.WriteLine("L'erreur suivante s'est produite : "+e.Message);
...
end try
- 类 Exception 包含一个方法 ToString,该方法返回一个字符串,其中包含异常类型以及属性 Message 的值。因此,我们可以这样编写:
catch ex as Exception
Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString)
...
end try
以下示例展示了因使用不存在的数组元素而引发的异常:
' 选项
Option Explicit On
Option Strict On
' 命名空间
Imports System
Module tab1
Sub Main()
' 数组的声明与初始化
Dim tab() As Integer = {0, 1, 2, 3}
Dim i As Integer
' 使用 for 循环显示数组
For i = 0 To tab.Length - 1
Console.Out.WriteLine(("tab[" & i & "]=" & tab(i)))
Next i
' 使用 for each 循环显示数组
Dim élmt As Integer
For Each élmt In tab
Console.Out.WriteLine(élmt)
Next élmt
' 抛出异常
Try
tab(100) = 6
Catch e As Exception
Console.Error.WriteLine(("L'erreur suivante s'est produite : " & e.Message))
End Try
End Sub
End Module
程序运行结果如下:
dos>exception1
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
0
1
2
3
L'erreur suivante s'est produite : L'index se trouve en dehors des limites du tableau.
以下是另一个示例,演示了当字符串不代表数字时,将字符串赋值给数字所引发的异常的处理方法:
' 选项
Option Strict On
Option Explicit On
'导入
Imports System
Public Module console1
Public Sub Main()
' 请求姓名
System.Console.Write("Nom : ")
' 读取回答
Dim nom As String = System.Console.ReadLine()
' 询问年龄
Dim age As Integer
Dim ageOK As Boolean = False
Do While Not ageOK
' 提问
Console.Out.Write("âge : ")
' 读取并验证回答
Try
age = Int32.Parse(System.Console.ReadLine())
If age < 0 Then Throw New Exception
ageOK = True
Catch
Console.Error.WriteLine("Age incorrect, recommencez...")
End Try
Loop
' 最终显示
Console.Out.WriteLine("Vous vous appelez [" & nom & "] et vous avez [" & age & "] ans")
End Sub
End Module
部分运行结果:
dos>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans
2.11. 向函数传递参数
这里我们关注函数参数的传递方式。考虑以下函数:
Sub changeInt(ByVal a As Integer)
a = 30
Console.Out.WriteLine(("Paramètre formel a=" & a))
End Sub
在函数定义中,a被称为形式参数。 它仅用于定义函数 changeInt。它同样可以命名为 b。现在让我们来看一下该函数的使用示例:
Sub Main()
Dim age As Integer = 20
changeInt(age)
Console.Out.WriteLine(("Paramètre effectif age=" & age))
End Sub
在此 changeInt(age) 语句中,age 是将值传递给形式参数 a 的实际参数。 我们关注的是形式参数如何获取与其对应的有效参数的值。
2.11.1. 按值传递
以下示例表明,函数/过程的参数默认采用值传递:即实际参数的值会被复制到对应的形式参数中。二者是两个独立的实体。如果函数修改了形式参数,实际参数则完全不受影响。
' 选项
Option Explicit On
Option Strict On
' 按值向函数传递参数
Imports System
Module param1
Sub Main()
Dim age As Integer = 20
changeInt(age)
Console.Out.WriteLine(("Paramètre effectif age=" & age))
End Sub
Sub changeInt(ByVal a As Integer)
a = 30
Console.Out.WriteLine(("Paramètre formel a=" & a))
End Sub
End Module
所得结果如下:
实际参数的值 20 被复制到了形式参数中 a。随后该形式参数被修改,而实际参数保持不变。这种传递方式适用于函数的输入参数。
2.11.2. 按引用传递
在引用传递中,实际参数和形式参数是同一个实体。如果函数修改了形式参数,实际参数也会随之改变。在 VB.NET 中,形式参数前必须加上关键字 ByRef。以下是一个示例:
' 选项
Option Explicit On
Option Strict On
' 向函数传递按值传递的参数
Imports System
Module param2
Sub Main()
Dim age As Integer = 20
changeInt(age)
Console.Out.WriteLine(("Paramètre effectif age=" & age))
End Sub
Sub changeInt(ByRef a As Integer)
a = 30
Console.Out.WriteLine(("Paramètre formel a=" & a))
End Sub
End Module
以及执行结果:
实际参数已跟随形式参数的修改。这种传递方式适用于函数的输出参数。

