VB.NET是怎样做到的(搬家版)[4]

[入库:2006年2月23日] [更新:2007年3月24日]

本文简介:

Public Class PropTest
    Public Property
P1(ByVal index As Integer) As String
       
Get

        End Get
        Set
(ByVal Value As String)

        End Set
    End Property


    Default Public Property P2(ByVal index As Integer) As String
       
Get

        End Get
        Set(ByVal Value As String)

        End Set
    End Property
End Class

P1和P2两个属性基本上完全相同,唯一的不同是P2带有一个Default修饰符。反汇编这个类以后,可以发现两个属性完全相同,没有任何差异。但是PropTest类却被增加了一个自定义元属性System.Reflection.DefaultMemberAttribute。这个元属性指定的成员是InvokeMember所使用默认类型,也就是说后期绑定也可以使用默认属性。可是我试验将DefaultMember元属性手工添加到类型上却不能达到让某属性成为默认属性的功能。看来这项功能又是VB的一项“语法甜头”。但是,VB或C#的编译器对别人生成的类的默认属性应该只能通过DefaultMemberAttribute来判断,所以我将一个VB类只用DefaultMemberAttribute指定一个默认方法,不使用Default,然后将它编译以后给C#用,果然,C#将它识别为一个索引器(indexer)!

既然说到了C#的索引器,我们就顺便来研究一下VB和C#属性方面的不同。刚才的实验结果是VB的默认属性在C#中就是索引器。但是VB仍然可以用属性的语法来访问默认属性,而C#只能用数组的语法访问索引器。更特别的是,VB可以创建不是默认属性,但是带有参数的属性,如上面例子里的P1,而C#则不支持带参数的属性,如果将VB编写的,含有带参数属性的类给C#用,C#会提示“属性不受该语言支持,请用get_XXX和set_XXX的语法访问”。也就是说,带参数的属性是CLR的一项功能,但不符合CLS(通用语言规范),因此就会出现跨语言的障碍。这也更加深了我们对CLS的认识——如果你希望让你的代码跨语言工作,请一定要注意符合CLS。

(七)可选参数和按名传递

VB从4.0开始支持“可选参数”这一特性。就是说,函数或子程序的参数有些是可选的,调用的时候可以不输入。其实VB从1.0开始就有一些函数带有可选参数,只不过到了4.0才让用户自己开发这样的过程。在VB4里,可选参数可以不带默认值,而在VB.NET里,如果使用可选参数,则必须带有默认值。如

Public Sub TestOptional(Optional i As Integer = 1)

End Sub

调用的时候,既可以写成TestOptional(2),也可以写成TestOptional(),这种情况参数i自动等于1。如果过程有不止一个可选参数,则VB还提供一种简化操作的方法——按名传递参数。比如过程

Public Sub TestOptional(Optional i As Int32 = 1, Optional j As Int32 = 1, Optional k As Int32 = 1)

End Sub

如果只想指定k,让i和j使用默认值,就可以使用按名传递,如下

TestOptional(k := 2)

而且这种方式不受参数表顺序的限制

TestOptional(k := 2, i := 3, j := 5)

这些的确是相当方便的功能,C#就不支持上述两个特性。我们看看它是怎样在IL级别实现的。上述第一个方法在IL中的定义为

.method public instance void TestOptional([opt] int32 i) cil managed
{
.param [1] = int32(0x00000001)
.maxstack 8

可见,参数被加上了[opt]修饰符,而且.param指定了参数的默认值。这是只有VB能识别的内容,C#会跳过他们。在调用的时候,VB若发现参数被省略,则自动读取.param部分的默认值,并显式传递给过程。这一部分完全由编译器处理,而且没有任何性能损失,和手工传递所有参数是完全一样的。至于按名传递,VB会自动调整参数的顺序,其结果与传统方式的传递也没有任何的不同。这说明我们可以放心地使用这项便利。而且带有可选参数的过程拿到C#中,顶多变成不可选参数,也不会造成什么其他的麻烦。

PS.很多COM组件都使用了默认参数,而且有些过程的参数列表非常长,在VB里可以轻松地处理它们,而在C#中经常让开发者传参数传到吐血。

(八)On Error语句和When语句

本次讨论的是异常处理语句。VB.NET推荐使用Try...End Try块来进行结构化的异常处理,但是为了确保兼容性,它也从以前版本的BASIC中借鉴了On Error语句。其实On Error并不能算是VB的优点,因为使用它会破坏程序的结构,让带有异常处理的程序难以看懂和调试。但是我一直很惊叹于VB的工程师是怎样实现它的,因为On Error可以让异常的跳转变得很灵活,不像Try那样受到限制。首先看看Try是怎样实现的:

本文关键:VB.NET是怎样做到的(搬家版)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top