VB.NET语法基础
在进行ASP.NET程序设计之前,首先要选择一种ASP.NET编程语言。ASP.NET的默认语言是Visual Basic.NET,当然也可以使用C#。本书主要介绍Visual Basic.NET,并且书中所有的例子都用Visual Basic.NET来编写。
本章介绍一些Visual Basic.NET的初步知识,关于VB.NET的高级编程知识请读者参阅其他相关图书。
Visual Basic.NET是继Visual Basic 6.0之后新发布的Visual Basic的全新版本。如果您是一个Visual Basic.NET的高手的话,可以跳过这一部分,从第3章开始学习。
学完本章后,读者将能够:
(1) 了解为什么选择VB.NET作为ASP.NET程序设计的首选语言;
(2) 了解变量、常量和表达式的知识;
(3) 会使用条件、循环语句;
(4) 了解如何使用过程和函数。
2.1 编程语言的选择
由于ASP.NET只是一个程序设计环境,要在这个环境中进行程序设计,必须选择一种语言。在早期的ASP中,默认使用的语言是VBScript脚本语言。由于.NET Framework已经支持VB等非脚本的高级语言,所以完全没有必要再去使用VBScript,但是原来用VBScript写的程序在ASP.NET中仍然可以执行,因为.NET环境仍然支持VBScript的语法。
2.1.1 .NET支持的语言
.NET为用户提供了三种程序设计语言:Visual Basic.NET、C#和Jscript。本节分别介绍这三种语言。
Visual Basic.NET是VB最新的版本,从功能和性能上讲可以说有了很大的飞跃。首先,早期的VB版本不完全支持面向对象的程序设计,由于它不支持对象的继承和重载,所以产生了很多问题。另外,早期的VB版本无法创建多线程的应用程序,这样就不能够充分利用机器的资源,也不能很好地提高应用程序的执行效率。但是现在,由于VB.NET使用了CLR,这些问题都很好地得到了解决。
对于C#,可以认为它是在C、C++的基础上创立的一种新的语言。它继承了C++的优异功能,去除了在.NET环境中没有用处的类型定义、模板等功能,使得C#与C++相比,更加易于使用,同时效率也大大提高。
与VB.NET一样,JScript.NET也是从JScript发展而来的。JScript.NET是完全用C#重新编写的,它支持类型和继承性,并且是完全编译执行的。为了保证原有的JScript程序仍然能够正确地执行,它仍然支持现有的JScript代码。
2.1.2 为什么选择VB.NET
本书选择VB.NET作为程序设计语言的原因是:首先,VB.NET是ASP.NET的默认编程语言;其次,VB.NET对于初学者来说十分简单易学,并且使用它可以完成C#和JScript.NET所能够完成的所有功能。
2.2 变量、常量和表达式
2.2.1 数据类型
VB.NET中有12种不同的数据类型,可以分成三类:数值类型、文本类型和混合类型。
数值类型是VB.NET数据类型的主要类型,共7种。数值类型的数据类型见表2-1。
表2-1 数值类型的数据类型
数据类型 |
表示方式 |
取 值 范 围 |
说 明 |
整型 |
Integer |
–2147483648~2147483647 |
用于表示简单整数 |
字节型 |
Byte |
0~255 |
用于简单算术运算。由于这个类型的变量可以在一个字节中存储,所以运算速度最快 |
短整型 |
Short |
–32768~32767 |
是整型的一种形式,相对表示范围较小 |
长整型 |
Long |
–9223372036854775808~ 9223372036854775807 |
是整型的一种形式,相对表示范围较大 |
单精 度型 |
Single |
–3.402823E38~–1.401298E-45(对于负数)和1.401298E-45~3.402823E38(对于正数) |
用于存放单精度浮点数 |
双精 度型 |
Double |
–1.79869313486232E308~ –4.94065645841247E-324(对于负数) 和4.94065645841247E-324~ 1.79869313486232E308(对于正数) |
用于存放双精度浮点数 |
小数 |
Decimal |
当小数位为0的时候,为 –79228162514264337593543950335~ 79228162514264337593543950335; 当小数位为28的时候,为 –7.9228162514264337593543950335~ 7.9228162514264337593543950335 |
常用于存储货币值 |
用于存放文本的数据类型有两个。文本类型的数据类型见表2-2。
表2-2 文本类型的数据类型
数 据 类 型 |
表 示 方 式 |
说 明 |
字符串型 |
String |
用于存放任何形式的字符串,包括一个字符或者多行字符 |
字符型 |
Char |
用于存放一个字符,它以0~65535之间数字的形式存储 |
其中需要说明的是:
(1) 对于String类型,可以存放任何形式的字符串,它可以是纯粹的文本,也可以是文本和数字的组合或者是数字、日期等。例如"This is a book. "和"12345"都是字符串。对于字符串类型的数据,可以进行相关的字符串操作,例如连接、截断等。
(2) 对于Char类型,可以存储的只是一个字符,注意,这个字符的存储编码必需是一个数字。在计算机系统中,可以显示很多符号(不仅仅是英文字母),为了能够正确地显示,国际上有通用的标准(例如Unicode编码),为每个字符设定了一个标准的数值来表示这个字符。
其余的数据类型还有:Date数据类型、布尔数据类型和Object数据类型,其说明见表2-3。
表2-3 其他数据类型
数 据 类 型 |
表 示 方 式 |
说 明 |
日期型 |
Date |
必须用mm/dd/yyyy的格式表示,也可以存储时间(可以存储00:00:00~23:59:59之间的任何时间) |
布尔型 |
Boolean |
取值为True和False |
对象型 |
Object |
|
其中需要说明的是:在VB.NET中,对于Boolean类型的数据,当需要把布尔类型的值转换为数值类型的时候,会把True当成1来处理,把False当作0来处理。当需要把数值类型的值转换为布尔类型的时候,会把0转换为False,而把其他的非0数值转换为True。
2.2.2 变量
变量用来存储程序中需要处理的数据,用户可以把变量看作是在内存中存储数据的盒子。在其他程序设计语言中,几乎都要求程序设计人员在使用变量之前定义变量的数据类型,因为不同数据类型的变量所需要的内存空间是不一样的:比如,字节型变量需要8位的空间,短整型变量需要16位空间等,这就表示盒子的容量是不一样的,所以为一种数据类型定义的变量就不能存放另一种数据类型的值。
在Visual Basic.NET中,创建变量的方式有两种:一种方法是使用Dim关键字,这是显式定义的方法。还可以使用隐式定义的方法,也就是在用户需要使用一个变量的时候直接写出这个变量并为它赋值。
显式定义方法如下所示:
Dim x
通过这样一条语句,就创建了一个名为x的变量。也可以用下面的方法一次定义多个变量:
Dim a,x
这条语句创建了两个变量:a和x。
在这里,有以下几点需要说明:
(1) 如何为变量取名字。Visual Basic.NET和其他语言一样,其变量名称必须以字母开头,只能包含字母、数字和下划线,并且不是Visual Basic.NET关键字。在为变量取名时,建议不要使用像a或者x这样的让人无法理解的变量名,而应该采用小写前缀加上有特定描述意义的名字的方式来为变量命名,这种命名方法被称为Hungarian法。变量名的前三个字母用于说明数据类型,第四个字母大写以表示变量的实际含义。例如下面的定义:
Dim strFileName
Dim intTotal
都可以说是定义了很好的变量名:用str和FileName两个部分组合来表示strFileName是用来存储字符串类型的文件名的,用int和Total两个部分组合来表示intTotal是用来存储整数类型的总和的。当然,对于程序员来说,这种命名约定并不是强制性的,仍然可以使用a和x这样的变量名,也可以用intTotal变量来存储一个字符串。但是很明显,如果用户都采用这种为变量命名的方式并在程序设计过程中遵循这样的好习惯,可以让程序易读,并减少出错的机会。
在VB.NET中,常用的约定前缀见表2-4。
表2-4 常用的变量命名约定
数 据 类 型 |
前 缀 |
例 子 |
Boolean |
bln |
blnYes |
Byte |
byt |
bytByte |
Char |
chr |
chrChar |
Date |
dat |
datDate |
Double |
dbl |
dblDouble |
Decimal |
dec |
decDecimal |
Integer |
int |
intTotal |
Long |
lng |
lngLong |
Single |
sng |
sngSingle |
Short |
sho |
shoShort |
String |
str |
strText |
Object |
obj |
objFileObject |
(2) 当使用Dim 语句的时候,可以在后面加上一个as关键字来指定一个变量的数据类型。例如:
Dim intTatal as Integer
这条语句表示创建一个名为intTatal的整数类型的变量,使用这种方法可以指明一个变量必须要保存什么类型的数据。虽然VB.NET并不强迫用户在定义变量的时候一定要指明其数据类型,但是建议用户在编写程序时使用这种方法来指明变量的数据类型,以减少程序出错的可能。
(3) 虽然可以使用隐式方法来创建变量,但是由于前面提到的原因,仍然建议使用显式的方法来定义变量。
(4) 在VB.NET中,是不区分大小写的,这就意味着,变量strFileName和变量strfilename将表示同一个变量。
2.2.3 运算符
在VB.NET中常用的运算符与其他的语言并没有什么不同。常用的运算符有:赋值运算符、算术运算符、字符串连接运算符、比较运算符和逻辑运算符。
1. 赋值运算符
赋值运算符是最常用的运算符,它就是我们熟悉的等号(=)。需要注意的是,虽然它表面上是一个等号,但它并不是一个数学意义上的等号,它的意思是把等号后边的值赋值给等号前面的变量。
例如,如果定义了一个整数型变量intNumber,就可以使用下面的语句:
Dim intNumber as Integer
intNumber=1
intNumber=intNumber*3
其中,第一行表示创建了一个名字为intNumber的整数型变量,第二行表示把这个变量的值赋值为2,第三行表示把intNumber中的值(也就是2)乘以3所得到的值(也就是6)赋值给intNumber。当第三条语句执行完成之后,intNumber中的值就是6。而在数学上,当intNumber的值是非零的时候,intNumber无论如何也不可能等于intNumber*3。
2. 算术运算符
VB.NET中的算术运算符有:+(加)、–(减)、*(乘)、/(除)、/(整数除)、Mod(取模)和^(幂),其中需要解释的是/(除)和/(整数除)的区别。/(除)表示的是通常意义的除法,例如,(5.4/3)的结果是1.8,而/(整数除)表示把除数和被除数四舍五入以后再计算除法得到的整数结果,所以在计算(5.4/3)时,把5.4四舍五入为5,再进行运算,得到的整数结果是1,这种运算在特定的应用中会十分有用。例如,你有89条消息需要发布,又不希望所有的89条信息都在一页中显示,而希望分页显示,而每页中只显示20条信息。那么(89/20)所得到的4就表示有4页是填满了20条信息的,而剩下的一页中有19条信息,并没有填满。
例2.1(02-01.aspx)VB.NET中算术运算符的用法。
1: <%
2: Dim dblData1,intData2,intData3
3: dblData1=5.4
4: intData2=3
5: intData3=7
6: Response.Write (dblData1+intData2 & "
") '5.4+3:结果是8.4
7: Response.Write (dblData1-intData2 & "
") '5.4-3:结果是2.4
8: Response.Write (dblData1*intData2 & "
") '5.4*3:结果是16.2
9: Response.Write (dblData1/intData2 & "
") '5.4/3:结果是1.8
10: Response.Write (dblData1/intData2 & "
") '5.4/3:结果是1
11: Response.Write (intData3 Mod intData2 & "
") '7 Mod 3:结果是1
12: Response.Write (intData3 ^ intData2 & "
") '7 ^ 3:结果是343
13: %>
需要说明的是:上面程序中第6行到第11行语句中的“&”运算符表示字符串的连接,另外,Response.Write表示输出后面括号中的字符串。
可以运行上面的程序来学习如何使用算术运算符。
3. 字符串连接运算符
在例2.1中可以使用第6行的dblData1+intData2得到一个Double类型的数和一个Integer类型的数进行相加的结果。对于两个字符串类型的变量,也可以使用“+”运算符。但是这时“+”运算符的含义不是加法,而是字符串的连接。例如:
Dim strTemp1,strTemp2 as String
strTemp1="Hello"
strTemp2="World. "
response.wirte(strTemp1 + " " + strTemp2)
当定义了两个字符串型变量strTemp1和strTemp2并给它们分别赋值之后,就可以使用第4行的“+”运算符把它们连接起来,并在中间夹了一个空格,形成"Hello World."字符串。
由于在算术运算符中“+”的含义与字符串运算的时候“+”的含义大不相同,所以为了减少误会的发生,在VB.NET中还可以使用“&”运算符作为字符串连接运算符。也就是说,当把第4行的语句换成
response.wirte(strTemp1 & " " & strTemp2)
后,仍然会得到正确的结果。建议使用“&”运算符进行字符串连接。
4. 比较运算符
VB.NET中的比较运算符有:=(等于)、<>(不等于)、<(小于)、<=(小于等于)、>(大于)、>=(大于等于)。这些运算符对于数值、字符、日期表达式的比较都是有效的,结果是布尔类型的True或False。
例2.2(02-02.aspx)VB.NET中的比较运算符的用法。
1: <%
2: Dim dblData1,intData2,intData3
3: dblData1=5.4
4: intData2=3
5: intData3=7
6: Response.Write ((dblData1>intData2) & "
") '5.4>3:结果是True
7: Response.Write ((dblData1
8: Response.Write ((dblData1=intData2) & "
") '5.4=3:结果是False
9: Response.Write ((dblData1>=intData2) & "
") '5.4>=3:结果是True
10: Response.Write ((dblData1<=intData2) & "
") '5.4<=3:结果是False
11: %>
可以运行上面的程序来学习如何使用比较运算符。
另外需要说明的是,字符串之间也是可以进行比较的,比较的方法是根据字母表的顺序。例如,“but”比“book”大,而“A”小于“a”。
5. 逻辑运算符
VB.NET中常用的逻辑运算符有:Not(非)、And(与)、Or(或)、Xor(异或)。计算的结果仍然是布尔类型的True或False。
例2.3(02-03.aspx)VB.NET中逻辑运算符的用法。
1: <%
2: Dim bolData1,bolData2 as Boolean
3: bolData1=True
4: bolData2=False
5: Response.Write ((bolData1 And bolData2) & "
") 'True And False是False
6: Response.Write ((Not bolData1) & "
") 'Not True是False
7: Response.Write ((bolData1 Or bolData2) & "
") 'True Or False是True
8: Response.Write ((bolData1 Xor bolData2) & "
") 'True Xor False是True
9: %>
可以运行上面的程序来学习如何使用逻辑运算符。
2.2.4 常量
常量是指在程序中直接给出的数值、字符或字符串。在程序中经常会使用这样的赋值语句:
intValue=3
strFileName="student.aspx"
在这里,3和"student.aspx"是常量。
在Visual Basic.NET中,有几个很特别的常量用户应该注意:
(1) Nothing:在VB.NET中,把一个表示对象的变量赋值为Nothing时,就表示这个对象不再使用,VB.NET会释放这个对象所占用的内存空间。使用的方法是:
objMyObject=Nothing
(2) Null:当一个变量的值是Null时,它表示这个变量的值不是有效数据。如果把变量形容成一个盒子,在没有给一个变量赋任何值的时候,VB.NET 会给它一个初始值(例如,如果用户定义了一个整型的变量,那么在没有使用它之前,它的值是0);而Null则表示这个盒子中的值是一个无效值。
(3) True:表示真。
(4) False:表示假。True和False通常用于条件语句。
另外一种常量是用Const关键字定义的。在定义变量的时候使用Const而不是Dim,并为这个变量赋一个值,就可以定义一个特殊的常量。这个常量以变量的形式出现在程序中,只是它的值在程序的执行过程中是不能改变的。由于它是一个不能改变的变量,所以有人也称它为常变量,也有人称之为符号常量。可以采用下面的方式定义一个表示路径名的符号常量:
Const strPathName="c:/windows"
这样,在后面的程序中,就可以使用strPathName来代表所有的“c:/windows”路径名,不用每次都指明。而且,如果程序发生变化,路径名要变成“c:/windows/cindy”,只要改动上面的这个定义语句就可以了。如果不采用常量,就需要修改程序中所有涉及到这个路径名的地方。
为了提高程序的效率,建议用户不要定义不需要使用的常量,因为所有的常量都要占用内存空间来进行保存。一旦定义了一个常量,系统就要在它的整个生存期内负责维护这个常量。对于大型的程序,往往会定义一个常量文件,把所有项目中会使用的常量都定义在这个文件中,在需要使用的时候把这个文件包含进来。这种方法虽然对于减少代码的复杂度很好,但是有一个问题,就是一个程序并不会使用包含文件中的所有常量。这样,很多常量是没有用的,但是这些常量却仍然要占用服务器的内存空间。由于在网络的环境中,客户的需求不好估计,往往很大,所以在定义常量时,要考虑清楚,才能保证程序的效率。
2.2.5 数组
除了使用单个变量,在VB.NET中还可以使用数组,以方便地存储一系列相关的数据。数组分为一维数组和多维数组。一维数组如下定义:
Dim arrData(2) as String
这个Dim语句定义了一个长度为3的一维数组arrData。它的下标的范围从0~2,即可以访问arrData(0)、arrData(1)、arrData(2),而数组中所有的数据都是String类型。
多维数组就是维数大于1的数组。最常见的是二维数组和三维数组。二维数组的定义方式如下:
Dim arrData(2,3) as String
这个Dim语句定义了一个3×4的数组,共有12个单元。与一维数组一样,它的下标范围是第一维从0~2,第二维从0~3。以此类推,可以定义三维数组或维数更多的数组。在VB.NET中数组的维数最多可以定义到60,但很少有人会用到维数超过三维的数组。
在VB.NET中还可以定义动态数组,即长度不确定的数组。例如,可以在程序开始的时候定义一个动态数组:
Dim arrData()
在这里,没有指明数组arrData的长度,也不知道它的维数,因此这个数组在程序中是不能直接使用的。因为所有的数组都需要有连续的内存空间来存放,如果没有定义数组的维数和每一维的长度,就意味着无法为数组分配内存空间。所以VB.NET要求在使用动态数组之前用ReDim语句为这个数组指明维数和每一维的长度。方法如下:
ReDim arrData(2)
这个时候,才可以使用arrData数组。注意,如果一个数组在定义的时候不是动态数组,就不能使用ReDim语句对数组重新定义。另外,对于已经使用ReDim重定义过的动态数组,可以使用ReDim重新再定义这个数组的长度,但是不能使用ReDim来重新定义数组的维数。也就是说,如果已经定义了一个动态数组arrData(),可以在后面的程序中把它重新定义为一个一维的数组(如ReDim arrData(2)),而不允许再把它定义为一个二维的数组(如ReDim arrData(2,3)),但是可以把它再次重定义为一个长度为5的一维数组(ReDim arrData(4))。
2.2.6 表达式
表达式是一个或多个运算的组合。VB.NET的表达式与其他语言的表达式没有显著的区别。每个符合VB.NET规则的表达式的计算都是一个确定的值。对于常量、变量的运算和对于函数的调用都可以构成最简单的表达式。
2.3 分支
到目前为止,我们已经学习了VB.NET的表达式的使用。现在,我们把它们用到更加复杂的结构中去。
在程序设计中,条件语句能够根据表达式的值来决定代码的执行流程。在VB.NET中,条件分支语句有两种:If/Then/Else语句和Select/Case语句。
1. If/Then/Else语句
If/Then/Else语句是最常用的条件语句。它的基本形式是:
If condition Then statements1 [Else statements2 ]
它表示:如果condition为True,那么就执行statements1;否则执行statements2。
例2.4(02-04.aspx)根据时间显示问候信息。
1: <%
2: If Hour(Now)<12 Then Response.Write ("Good morning! Cindy!")
3: If Hour(Now)=12 Then Response.Write ("Good noon! Cindy!")
4: If (Hour(Now)>12 And Hour(Now)<18) Then Response.Write ("Good afternoon! Cindy!")
5: If Hour(Now)>=18 Then Response.Write ("Good evening! Cindy!")
6: %>
在上面的例子中,函数Hour()是对给出的日期时间求它的小时数,Now函数用于返回当前的日期和时间。程序根据当时的时间判定是上午、中午还是下午,分别给出问候信息。我们看到,这个写法很简单,但是这个程序为了显示一条问候信息,要对Hour(Now)取值4次并且执行4次比较才能完成,从效率上考虑并不好。
If/Then/Else语句还可以写成比较复杂的形式:
If condition_1 Then
statements_1
[ElseIf condition_m Then
statements_m
[ElseIf condition_n Then…]]
[Else
statements_2]
End If
这个语句可以检测多个条件。第一种写法要求语句在写的时候要在一行中写完,例如例2.4 的第2行的If语句。这条语句也可以采用第二种方法来写,方法如下:
If Hour(Now)<12 Then
Response.Write ("Good Morning!Cindy!")
End If
建议用户采用后一种写法,因为这种方法更结构化,可读性好。当用户在调试大型软件的代码时,会发现,虽然看起来多写了几行语句,但好处却是很大的。
例2.5(02-05.aspx)根据时间显示问候信息。请注意这个例子的写法与上个例子中的写法在执行效率上的区别。
1: <%
2: If Hour(Now)<12 Then
3: Response.Write ("Good morning! Cindy!")
4: ElseIf Hour(Now)=12 Then
5: Response.Write ("Good noon! Cindy!")
6: ElseIf Hour(Now)>=18 Then
7: Response.Write ("Good evening! Cindy!")
8: Else
9: Response.Write ("Good afternoon! Cindy!")
10: End If
11: %>
上面的例子在执行的过程中,对于当前不同的时间,为了显示问候信息,执行的Hour(Now)的取值和比较的次数是不一样的:最少只要1次,最多需要3次。从效率上看,比例2.4要好。
2. Select/Case结构
当程序中的条件比较复杂,而且是根据同一个表达式的不同值执行不同操作的时候,用If/Then/Else语句来写就显得十分烦琐。这时可以考虑采用Select/Case结构来完成条件语句。
Select/Case结构为:
Select Case testexpression
Case condition_1
statements_1
[ …
Case Else
statements_n]
End Select
它表示:如果testexpression的值是Condition_1,就执行statements_1,以此类推,如果都不符合,就执行Statements_n。
例2.6(02-06.aspx)用Select/Case语句来实现问候信息的显示。
1: <%
2: Select Case Hour(Now)
3: Case 0,1,2,3,4,5,6,7,8,9,10,11
4: Response.Write ("Good morning! Cindy!")
5: Case 12
6: Response.Write ("Good noon! Cindy!")
7: Case 13,14,15,16,17
8: Response.Write ("Good afternoon! Cindy!")
9: Case Else
10: Response.Write ("Good evening! Cindy!")
11: End Select
12: %>
很明显,用这种方法来显示问候信息要比用If/Then/Else语句清楚得多。因此,在选择条件语句的时候要考虑好采用什么方式,并认真设置好条件。
2.4 循环
VB.NET中的循环有三种形式:For/Next、While/End While、Do/Loop和For/Each。
1. For/Next循环
用For/Next循环可以精确地控制循环体的执行次数。For/Next循环的语法如下:
For counter = startvalue To endvalue [Step stepvalue]
[statements]
[Exit For]
[statements]
Next
其中,用Step关键字可以定义循环计数器的增长方式,stepvalue的值(可正可负)来适应各种不同的需求。Exit For语句允许在某种条件下直接退出循环体。
例2.7(02-07.aspx)用For/Next语句来实现显示二维数组的内容。
1: <%
2: Dim arrData(1,2)
3: Dim intI,intJ as Integer
4: arrData(0,0)=12
5: arrData(0,1) =13
6: arrData(0,2) =14
7: arrData(1,0) =15
8: arrData(1,1) =16
9: arrData(1,2) =17
10: For intI=0 To 1
11: For intJ=0 To 2
12: Response.Write (arrData(intI,intJ) & " ")
13: Next
14: Response.Write ("
") '一行显示完以后换行显示下一行
15: Next
16: %>
可以看出,用For/Next循环来显示数组这样的可以确定循环次数的数据结构是十分方便的。
2. While/End While 循环
如果不清楚要执行的循环的次数,那么可以用While/ End While循环。它有一个检测条件,当条件满足时,执行循环体的内容。如果条件不满足,就退出循环。While/ End While语法如下:
While condition
[statements]
End While
由于在进入循环体之前会遇到检测条件,所以如果这个时候condition的值为False,那么While/ End While循环的循环体有可能一次也不能执行。
例2.8(02-08.aspx)显示3次问候信息。
1: <%
2: Dim intI as Integer
3: IntI=0
4: While intI<3
5: Response.Write ("Hello! Cindy!" & "
")
6: IntI=intI+1
7: End While
8: %>
在这个例子的第3行中为第2行中定义的intI变量设置了初值0。这里,如果不设置初值也是可以的,系统会自动为intI进行初始化(VB.NET默认为未显式初始化的整数初始化为0)。但是,建议养成为变量设置初值的好习惯,这样可以防止很多意想不到的错误。
3. Do/Loop
同样,在不知道循环次数的情况下,也可以使用Do/Loop 循环。Do/Loop循环的作用与While/ End While十分相似。它的语法是:
Do {While | Until} condition
[statements]
[Exit Do]
[statements]
Loop
其中,Do后面的While和Until是可选的。使用While时,后面的条件满足则执行循环体;使用Until时,后面的条件满足就退出循环体。Do/Loop循环还有另外一种写法:
Do
[statements]
[Exit Do]
[statements]
Loop {While | Until} condition
这种写法的结果是:循环体在执行的时候至少会执行一次。
例2.9(02-09.aspx)显示3次问候信息。
1: <%
2: Dim intI
3: IntI=0
4: Do Until intI>2
5: Response.Write ("Hello! Cindy!" & "
")
6: IntI=intI+1
7: Loop
8: %>
可以看出,Do/Loop的执行和While/End While的执行没有太大的区别。用户也可以把上面例子中第4行中的Until改为While并相应地改变后面的条件来实现相同的功能。
4. For/Each
在某些特殊情况下,可以使用For/Each来实现对一个数组或集合(集合将在后面的章节中讲解)中元素的遍历。
For/Each语句的写法如下:
For Each item In Array or Collection
[statements]
Next
例2.10(02-10.aspx)用For/Each显示一个数组中的所有数据。
1: <%
2: Dim arrData(3)
3: Dim stritem as string
4: arrData(0)="Beijing"
5: arrData(1)="Shanghai"
6: arrData(2)="Guangzhou"
7: For Each stritem In arrData
8: Response.Write (stritem & "
")
9: Next
10: %>
可以看出,For/Each循环与For/Next循环的区别是:在For/Next循环中需要指明循环的次数,而在For/Each循环中不需要这样就可以遍历到一个数组或集合的所有内容。另外需要说明的是,这种循环通常在集合中使用。
2.5 过程和函数
在程序设计过程中,随着代码量的不断增加,会出现很多地方使用同样代码的情况。为了能够减少同样代码的编写,ASP.NET允许使用一些小的程序将重复的代码只写一次,其他需要使用这段代码的地方调用这个小程序就可以了。
在ASP.NET中,实现这种小程序的方式有两种:过程和函数。
2.5.1 模块化的优点
模块化是在程序设计发展到一定程度的时候诞生的程序设计方法。在早期的程序设计过程中,由于机器的硬件配置低,所以程序的运行速度和效率十分重要,因此早期的程序设计人员会大量使用各种技巧保证程序的快速运行,而这些技巧导致的最直接后果就是程序的结构混乱,很难阅读。
随着机器硬件的不断更新,这些编程技巧所提高的程序运行速度已经微不足道,这时提高程序的可读性就变得十分重要,于是就出现了模块化程序设计方法。
模块化程序设计方法的特点是:在编写程序之前,把程序的功能分解成若干个小的任务,并把这些小任务看成是一个一个的模块。当各个模块编写完成之后,就可以把这些模块编译成为一个大型的程序。由于每个模块都有自己独立的功能,所以可以把这些模块分配给很多程序员来完成;而每个模块的功能都是详细定义的,所以可以建立完善的文档,使得程序的可读性大大提高。
2.5.2 过程和函数
VB.NET支持子过程和函数,它们都可以根据需要设置参数。它们之间惟一的区别是函数可以有返回值而子过程没有。
子过程的定义方式为:
Sub subname ([argument1[,…, argumentn]])
[statements]
End Sub
对于子过程的调用方式是直接调用过程名subname。如果有参数,就在后面按照次序将参数在括号中写好。
例2.11(02-11.aspx)用一个子过程显示对一个用户的问候信息:
1:
2: Sub SayHello(strUserName as String)
3: Response.Write ("Hello!" & strUserName & "
")
4: End Sub
5:
6: <%
7: SayHello("Cindy")
8: %>
在上面的例子中,有下面几点需要说明:
(1) 在第1行~第5行使用
7: <%
8: Dim intTemp1,intTemp2 as Integer
9: intTemp1=2
10: intTemp2=3
11: Response.Write(Add(intTemp1,intTemp2))
12: Response.Write("
")
13: Response.Write(intTemp1)
14: %>
在上面的程序中,有下面几点需要说明:
(1) 在第2行~第5行定义了一个函数Add。这个函数带有两个参数:intData1和intData2,并把一个整数作为返回值。
(2) 在第3行把参数intData1与intData2的和放到intData1中,并在第4行把intData1作为结果返回。
(3) 在第11行调用了这个函数,并把结果显示出来。
在上面的子过程和函数的讲解过程中,可以看出都可以采用带参数的方式来增加子过程和函数的灵活性。需要说明的是,参数的传递有两种方式:通过值传递参数和通过引用传递参数。
在调用子过程和函数的时候,如果没有明确地指出,所有的参数都是通过值进行传递的。所谓通过值进行传递,就是把参数的值复制到参数中。例如例2.12中第11行的Add(intTemp1,intTemp2),就是通过值进行传递的好例子。在真正执行第2行~第5行定义的Add函数时,是把intTemp1的值2复制给了intData1,把intTemp2的值3复制给了intData2。在第3行把intData1和intData2的和赋值给intData1的时候,intData1的值变成了5,但是这个时候,intTemp1的值仍然是2,不是5(通过第13行的执行可以看出来),这就是通过值传递参数。这时,intData1和intTemp1是两个不同的变量,在内存中占用不同的存储空间。
在函数和子过程中,使用关键字ByVal来显式表示通过值传递参数。也就是说,如果要用显式的方式进行定义,第2行的函数定义可以写成:
Function Add(ByVal intData1 as Integer, ByVal intData2 as Integer) as Integer
默认的情况是采用通过值传递参数。
那么什么是通过引用传递参数呢?请先看下面的例子。
例2.13(02-13.aspx)用一个函数计算两个整数的和。
1:
2: Function Add(ByRef intData1 as Integer,ByRef intData2 as Integer) as Integer
3: intData1=intData1+intData2
4: Return intData1
5: End Function
6:
7: <%
8: Dim intTemp1,intTemp2 as Integer
9: intTemp1=2
10: intTemp2=3
11: Response.Write(Add(intTemp1,intTemp2))
12: Response.Write("
")
13: Response.Write(intTemp1)
14: %>
例2.13与例2.12的区别就在于第2行的Add函数的定义。在这里使用了ByRef关键字表示这时的参数是通过引用进行传递的。执行这个程序就会发现,在程序执行完之后,不但intData1的值变成了5,同时intTemp1的值也变成了5。
通过引用传递参数的方法是把参数的地址传递进去。在第11行进行传递的时候,不是把intTemp1的值复制给intData1,把intTemp2的值复制给intData2,而是把intTemp1的地址给了intData1的地址,把intTemp2的地址给了intData2的地址。在传递成功之后,intData1就是intTemp1,intData2就是intTemp2。所以在第3行intData1的值发生变化时,intTemp1的值也同时发生了变化。
2.5.3 变量的作用域
在进行变量声明时,变量声明的位置决定了这个变量的作用范围。在一个过程或函数外声明的变量是全局变量,对本程序内部所有的过程和函数都起作用;而在一个过程或函数内部声明的变量是局部变量,只对本过程或函数起作用。
下面通过一个例子说明全局变量和局部变量的区别。
例2.14(02-14.aspx)全局变量和局部变量的使用。
1:
2: Dim strGlobal as String="global"
3: Sub SayHello
4: Dim strTemp as String="hello!"
5: Response.Write (strTemp & "
")
6: Response.Write (strGlobal & "
")
7: if strGlobal<>"" then
8: Dim strTemp1 as String="hello cindy!"
9: Response.Write (strTemp1 & "
")
10: end if
11: 'Response.Write (strTemp1 & "
")
12: End Sub
13:
14: <%
15: SayHello
16: %>
上面的例子中,有下面几点需要说明:
(1) 第2行声明的变量strGlobal定义在所有的函数或者过程之外,所以是一个全局变量。由于在定义这个变量的时候就为这个变量赋值为“global”,所以,在后面的程序中,第一次使用这个变量时这个变量的值就是“global”。
(2) 第3行~第12行定义了一个子过程SayHello。在这个过程中,首先在第4行定义了一个变量strTemp,由于这个变量是定义在子过程中的,所以这个变量是一个局部变量。在第5行显示这个变量的值的时候,会显示一个“hello!”字符串。
(3) 第6行要显示strGlobal的值,由于这是一个全局变量,所以会显示第1行赋值的“global”。
(4) 第7行~第10行定义了一个If/Endif代码块,在这个代码块中,定义了一个块级局部变量strTemp1(第8行)。由于这个变量是定义在代码块中的,所以只在这个代码块中起作用。所以在第9行要显示它的值的时候,会显示“hello cindy!”。而如果取消第11行的注释,系统将会通告strTemp1变量没有定义。
通过上面的例子可以看出,在编写程序的时候,要时刻注意变量的作用域的问题。因为在不同模块中修改全局变量会导致模块之间相互影响,违反了进行模块化程序设计的初衷。所以要设计好的程序,就应该尽量减少全局变量的使用