Evil 域

当Evil遇上先知

导航

VB 9.0新特性之对象初始化器(Object Initializers)(二)

Posted on 2008-06-16 21:34  Saar  阅读(871)  评论(0编辑  收藏  举报
MP3 + 大容量存储 = iPod,这个公式告诉我们,当两个东西结合在一起的时候,就有可能产生新的力量。当对象初始化器与匿名类相碰,会产生什么像的新特性?
VB 9.0新特性之对象初始化器(Object Initializers)(一)中我们看到了,新的编译器允许我们通过简简单单一行代码,来完成一个对象的创建与初始化。让我们回顾一个典型的代码:
1Dim myNoteBook = New Notebook With {.Brand = "Lenovo", .Price = 16000, .Type = "T61", .Weight = 2.3}
我们通过New关键字,创建了一个Notebook对象,然后,通过With { 属性及初始值 }来完成myNoteBook对象的创建,并且,给它的四个属性分别赋了四个值。
大家来看看下面这行代码跟前面的这一行有什么差别:
1Dim myNoteBook = New With {.Brand = "Lenovo", .Price = 16000, .Type = "T61", .Weight = 2.3}
一个最明显的差别是:代码变短了!!^_^嘿嘿,是变短了没有错,少了什么呢?呵呵,大家注意到,New关键字后面的类型没有了。天哪,那这个myNoteBook到底是什么类型的对象?这样的代码在VB9.0里也合法?没错,对于局部变量,这是合法的。它的类型是:!@#$%^&*()……呵呵,它是一个匿名类型。而且,不同编译器给出的匿名类型的类名还有可能不一样。
我们来看一下这样一行代码背后到底发生了什么:
首先,编译器会创建一个类,这个类的类名也许是A,也许是B,也许是……天知道,但在这里,这不重要,重要的是:通过后面的表达,我们知道,这个类有四个属性;
第二步,编译器用这个类初始化一了一个实例:myNoteBook;
第三步,编译器用初始化器给这个实例作初始化,对其四个属性分别赋予对应的初始值。
可以看到,虽然从形式上,匿名类型的对象初始化器与命名类的对象初始化器相比只少了一个类名,但是,背后发生的故事却完全不同。它们的With子句都不能为空,即不可以什么都不初始化。但是,命令类型的初始化器初始化的属性,必须是在其声明的类中拥有声明的属性;而匿名类中属性,则是通过局部类型推断来创建的。也就是说,以下的匿名类对象初始化器是合法的:
1         Dim myLaptop1 = New With {.Brand = "IBM", .Series = "T"}
2         Dim myLaptop3 = New With {noteBooks(2).Brand}

第1行,编译器会“偷偷的”创建一个匿名类,根据局部类型推断,这个类拥有两个String类型的属性,然后,创建myLaptop1的实例,其Brand为“IBM”、Series为“T”。第二行中,noteBooks(2)是VB 9.0新特性之对象初始化器(Object Initializers)(一)一文中的Notebook类的对象数组。我们取其中第3个noteBook的Brand作为这个匿名类的Brand属性。因此,第二个匿名类会有一个Brand属性,其对象myLaptop3的Brand值与noteBooks(2)的Brand的值一致。

由于这个匿名类型“没有名分”,因此,其使用也有各种各样的限制:
第一,匿名类的属性的类型,必须是通过局部类型推断来获得的。
1         Dim myLaptop1 = New With {.Brand = "IBM", .Series = "T"}
2         'this is illegal
3         'Dim myLaptop2 = New With {.Brand As String = "IBM", .Series = "T"}
第二,对于用另一个对象的属性来初始化时,要注意不可以出现重复属性:
1         'not valid
2         'Dim myLaptop4 = New With {noteBooks(2).Brand, .Brand = "Lenovo"}
3         'valid
4         Dim myLaptop5 = New With {.OldBrand = noteBooks(2).Brand, .Brand = "Lenovo"}
当出现属性名称的属性时,必须显式的将其区分开来,如上述第4行的对象创建是成功的,它会形成一个OldBrand属性,一个Brand属性的匿名类。
第三,对象初始化时,按顺序从左至右初始化,并且,不可以使用未初始化的属性作为参数来进行初始化操作。
1         'not valid
2         'Dim myLaptop6 = New With {.Brand = .Name, .Name = "IBM"}
3         Dim myLaptop7 = New With {.Name = "IBM", .Brand = .Name}

呵呵,这样看来,匿名类型的对象初始化器似乎实在是没有给我们带来什么啊,毕竟是编译器偷偷模模创建出来的东西啊~就匿名类型的对象初始化器而言,感觉的确没有太多实际的用途,但是,它在LINQ里,占有着重要的地位。因此,对匿名类型的对象初始化器的理解,有助于对LINQ的深入理解。