科技时代新浪首页 > 科技时代 > 软件 > 正文

老树新芽 体验Visual Basic 9.0新功能(6)


http://www.sina.com.cn 2005年09月27日 18:05 天极yesky

    空类型

  关系数据库引入了空值的语义,空值和当前的普通程序设计语言经常不一致,程序员也不熟悉它。在以数据为中心的程序中,正确清晰地理解这些语义是很重要的。考虑到这一点,在"Whidbey"里CLR使用泛型Nullable(Of T As Struct)加入了对空特性的运行时支持。使用这个类型我们可以声明各种值类型的空版本,如Integer,Boolean和Data等等。为了明显起见,VB中空类型的语法为T?。

  举例来说,并不是所有国家都是独立的,我们可以给类Country加上一个新的成员代表他们的独立时间:

Partial Class
 Country Public Property Independence As Date?
End Class

  和数组类型一样,我们也可以给属性名加上可为空的修饰语,如下声明:

Partial Class
 Country Public Property Independence? As Date
End Class

  帕劳群岛的独立时间是#10/1/1994#,不过Virgin岛是英联邦的属地,因而它的独立日是Nothing:

Dim Palau = _
 New Country { _
  .Name = "Palau", _
  .Area = 458, _
  .Population = 16952, _
  .Independence = #10/1/1994# }
Dim VirginIslands = _
 New Country { _
  .Name = "Virgin Islands", _
  .Area = 150, _
  .Population= 13195, _
  .Independence = Nothing }

  Visual Basic 9.0支持在空值上的三值逻辑和空传播算术,这意味着如果其中一个算术,比较,逻辑或者位,转换,或者类型操作的操作数是Nothing,结果就是Nothing。如果两个操作数都是适当的值,操作将根据操作数的值来决定,结果被转化为空。

  因为Palau.Independence和VirginIslands.Independence都是Date?类型,编译器将使用空传播算术来进行下面的提取,因此对于本地声明PLength和VILength的推断类型就都是TimeSpan?。

Dim PLength = #8/24/2005# - Palau.Independence REM 3980.00:00:00

  PLength的值是3980.00:00:00因为没有操作数是Nothing。另外,由于VirginIslands.Independence的值是Nothing,结果类型也是TimeSpan?,但是因为空传播的原因VILength的值是Nothing。

Dim VILength = #8/24/2005# - VirginIslands.Independence REM Nothing

  在SQL里,比较操作符将会做空传播,逻辑员算府将会使用三值逻辑。在If和While语句中,Nothing将会理解为False;因此在如下代码里,使用了Else分支:

If VILength < TimeSpan.FromDays(10000)
 ...
Else
 ...
End If

  注意在三值逻辑里,等式检查X = Nothing,但是Nothing = X总是等同于Nothing;为了检查X是否是Nothing,我们应该用双值逻辑比较X Is Nothing或者Nothing Is X。

  在打包和解包时,运行时将会把控制看作是Object来处理。当打包一个代表Nothing的空值时(HasValue属性为False),值将会被打包进一个空引用。当打包一个合适的值时(HasValue属性为True),当前值将会首先被解开,然后再打包。因为这样,没有堆里的对象是动态类型Nullable(Of T);所有这样明显的类型都是T。同时,我们也可以从Object中解包值然后放入到T或者Nullable(Of T)。然而,这样做的结果是后期绑定不能动态的决定是否使用三值逻辑或者双值逻辑。举例来说,当我们做一个两个数的早期绑定的相加时,一个数是Nothing,将使用空操作,结果就是Nothing:

Dim A As Integer? = Nothing
Dim B As Integer? = 4711
Dim C As Integer? = A+B
REM C = Nothing

  然而,当使用两个值的后期绑定相加时,结果是4711,因为A和B的动态类型都是Integer而不是Integer?,后期绑定将会使用双值逻辑。这里Nothing被解释为0:

Dim X As Object = A
Dim Y As Object = B
Dim Z As Object = X+Y
REM Z = 4711

  为了保证正确地语义,我们需要引导编译器使用空传播重载:

Operator +(x As Object?, y As Object?) As Object?

  通过使用?操作符转化任意一个操作数为空类型:

Dim X As Object = A
Dim Y As Object = B
Dim Z As Object? = X?+Y
REM Z = Nothing

  注意这里我们必须能够从任何类型T来创建T?。当前的CLR Nullable(Of T As Struct)类型限制只能使用非空结构的参数类型。T如果不是一个非空值的类型,Visual Basic编译器将会把T?转化为T,否则转化为Nullable(Of T)。编译器将会在VB程序里保留足够的内部元数据以记住载此两种情况下静态类型都是T?。

  非严格委托

  当使用AddressOf或者Handles在Visual Basic 8.0创建一个委托时,要和委托标识符绑定的方法之一必须要和委托类型的署名相一致。在如下例子中,OnClick子程序的署名必须和事件句柄委托Delegate Sub EventHandler(sender As Object, e As EventArgs)一致,该委托是在Button类型后声明的:

Dim WithEvents B As New Button()
Sub OnClick(sender As Object, e As EventArgs) Handles B.Click
 MessageBox.Show("Hello World from" + B.Text)
End Sub

  然而,当调用非委托函数和子程序时,Visual Basic并不需要实际的参数严格符合我们想要调用的某个方法。就和下面的程序段显示的一样,我们实际上使用了一个Button类型和MouseEventArgs类型作为参数来调用OnClick子函数,它们分别是前面参数Object和EventArgs的子类型:

Dim M As New MouseEventArgs(MouseButtons.Left, 2, 47, 11,0) OnClick(B, M)

  相反的,假设我们定义了一个子程序RelaxedOnClick,它接受两个Object参数,那么我们允许使用Object和EventArgs类型的参数来调用它:

Sub RelaxedOnClick(sender As Object, e As Object) Handles B.Click
 MessageBox.Show("Hello World from" + B.Text))
End Sub
Dim E As EventArgs = M
Dim S As Object = BRelaxedOnClick(B,E)

  在Visual Basic9.0里,和委托绑定和方法调用是非严格一致的。也就是说,如果有可能去使用严格符合一个委托的原定参数和返回类型的参数来调用一个函数或者子程序,我们就可以将函数和子程序同委托绑定。委托绑定和定义将会参照之后的方法调用采用相同的重载解析逻辑。

  这暗示了在Visual Basic 9.0中我们可以将一个接受两个Object参数的子程序RelaxedOnClick和一个Button的Click事件绑定起来:

Sub RelaxedOnClick(sender As Object, e As Object) Handles B.Click
 MessageBox.Show(("Hello World from" + B.Text)
End Sub

  事件句柄的两个参数,sender和EventArgs,没有太大的关系。句柄将会通过事件直接注册的control来访问control的状态,忽略掉它的两个参数。为了支持一般的情况,委托可以非严格的不接受参数,如果没有混淆结果的话。因此,我们可以这样简写如下:

Sub RelaxedOnClick Handles B.Click
 MessageBox.Show("Hello World from" + B.Text)
End Sub

  现在比较清楚的是,非严格委托也应用在使用AddressOf创建委托或者委托创建表达式里,特别是方法组是一个后期绑定的调用时:

Dim F As EventHandler = AddressOf RelaxedOnClick
Dim G As New EventHandler(AddressOf B.Click)

[上一页] [1] [2] [3] [4] [5] [6] [7] [下一页]

发表评论

爱问(iAsk.com)



评论】【论坛】【收藏此页】【 】【多种方式看新闻】【下载点点通】【打印】【关闭




科技时代意见反馈留言板 电话:010-82628888-5595   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2005 SINA Inc. All Rights Reserved

版权所有 新浪网