vbnet龚沛曾第二版的简单介绍( 五 )


4.21局部静态变量
VB支持用Static关键字声明局部变量,这样在过程结束的时候可以保持变量的数值:
Public Sub Test1()
Static i As Integer
i += 1 '实现一个过程调用计数器
End Sub
我们实现了一个简单的过程计数器 。每调用一次Test,计数器的数值就增加1 。其实还有很多情况我们希望保持变量的数值 。而C#的static是不能用在过程内部的 。因此要实现过程计数器,我们必须声明一个类级别的变量 。这样做明显不如VB好 。因为无法防止其他过程修改计数器变量 。这就和对象封装一个道理,本来应该是一个方法的局部变量,现在我要被迫把它独立出来,显然是不好的设计 。那么VB是怎么生成局部静态变量的呢?将上述代码返汇编,我们可以清楚地看到在VB生成的CIL中 , i不是作为局部变量 , 而是作为类的Field出现的: .field private specialname int32 $STATIC$Test1$2001$i
也就是说,i被改名作为一个类的字段,但被冠以specialname 。在代码中试图访问$STATIC$Test1$2001$i是不可能的,因为它不是一个有效的标识符 。但是在IL中,将这个变量加一的代码却与一般的类字段完全一样 , 是通过ldfld加载的 。我觉得这个方法十分聪明 , 把静态变量变成生命周期一样的类字段,但是又由编译器来控制访问的权限,让它成为一个局部变量 。同时也解释了VB为什么要用两个不同的关键字来声明静态变量——Static和Shared 。由于局部静态变量的实质是类的字段,所以它和真正的局部变量还是有所不同的 。比如在多线程条件下 , 对局部静态变量的访问就和访问字段相同 。
4.2.2Handles和WithEvents
VB除了可以用C#那样的方法来处理事件响应以外,还有从VB5继承下来的独特的事件处理方式——WithEvents 。
我喜欢称这种事件处理方式为静态的事件处理,书写响应事件的方法时就已经决定该方法响应的是哪一个事件,而C#则是在代码中绑定事件的 。VB中WithEvents静态方法是非常有用的 , 它可以显著增强代码可读性,同时也让VB.net中的事件处理非常方便,不像C#那样离开了窗体设计器就必须手工绑定事件 。
4.2.3类型转换运算符
在Visual Basic 2005中将加入一个新的运算符——TryCast,相当于C#的as运算符 。我一直希望VB有这样一个运算符 。VB目前的类型转换运算符主要有CType和DirectCast 。他们的用法几乎一样 。我详细比较了一下这两个运算符,得出以下结论:
1.在转换成引用类型时 , 两者没有什么区别 , 都是直接调用castclass指令,除非重载了类型转换运算符CType 。DirectCast运算符是不能重载的 。
【vbnet龚沛曾第二版的简单介绍】2.转换成值类型时 , CType会调用VB指定的类型转换函数(如果有的话) , 比如将String转换为Int32时 , 就会自动调用 。
4.2.4默认属性和属性参数
在原先的VB6里,有一项奇特的功能——默认属性 。在VB6中,对象的名称可以直接表示该对象的默认属性 。
4.2.5可选参数和按名传递
VB从4.0开始支持“可选参数”这一特性 。就是说,函数或子程序的参数有些是可选的,调用的时候可以不输入 。其实VB从1.0开始就有一些函数带有可选参数,只不过到了4.0才让用户自己开发这样的过程 。在VB4里,可选参数可以不带默认值,而在VB里,如果使用可选参数,则必须带有默认值 。在调用的时候,VB若发现参数被省略,则自动读取.param部分的默认值,并显式传递给过程 。这一部分完全由编译器处理,而且没有任何性能损失,和手工传递所有参数是完全一样的 。至于按名传递,VB会自动调整参数的顺序,其结果与传统方式的传递也没有任何的不同 。这说明我们可以放心地使用这项便利 。而且带有可选参数的过程拿到C#中,顶多变成不可选参数,也不会造成什么其他的麻烦 。

推荐阅读