在向大家详细介绍VB.NET默认属性之前,首先让大家了解下TextBox的默认属性是Text,然后全面介绍VB.NET默认属性。在原先的VB6里,有一项奇特的功能——默认属性。在VB6中,对象的名称可以直接表示该对象的默认属性。比如TextBox的默认属性是Text,所以下面的代码
- Text1.Text = "Hello"
就可以简化为
- Text1 = "Hello"
这种简化给VB带来了很多麻烦,赋值运算就需要两个关键字——Let和Set,结果属性过程也需要Let和Set两种。而且这种特征在后期绑定的时候仍能工作。到了VB.NET,这项功能被大大限制了,现在只有带参数的属性才可以作为默认属性。如
- List1.Item(0) = "Hello"
可以简化为
- List1(0) = "Hello"
这种语法让有默认属性的对象看起来像是一个数组。那么VB怎么判断一个属性是否是默认属性呢?看下列代码
- 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.NET默认属性在C#中就是索引器。但是VB仍然可以用属性的语法来访问默认属性,而C#只能用数组的语法访问索引器。更特别的是,VB可以创建不是默认属性,但是带有参数的属性,如上面例子里的P1,而C# 则不支持带参数的属性,如果将VB编写的,含有带参数属性的类给C#用,C#会提示“属性不受该语言支持,请用get_XXX和set_XXX的语法访问”。也就是说,带参数的属性是CLR的一项功能,但不符合CLS(通用语言规范),因此就会出现跨语言的障碍。这也更加深了我们对CLS的认识——如果你希望让你的代码跨语言工作,请一定要注意符合CLS。
【编辑推荐】