如何:推断匿名类型声明中的属性名和类型 (Visual Basic)
匿名类型不提供直接指定属性的数据类型的机制。 所有属性的类型都是推断出来的。 下面的示例从用于初始化属性的值,直接推断 Name
和 Price
属性的类型。
' Variable product is an instance of a simple anonymous type.
Dim product = New With {Key .Name = "paperclips", .Price = 1.29}
匿名类型还可以从其他来源推断属性名和类型。 以下各部分提供了可以进行推断的情况列表,以及不能进行推断的情况的示例。
成功推理
匿名类型可以从以下来源推断属性名和类型:
从变量名称。 匿名类型
anonProduct
将具有两个属性:productName
和productPrice
。 它们的数据类型将是原始变量的数据类型,分别为String
和Double
。Dim productName As String = "paperclips" Dim productPrice As Double = 1.29 Dim anonProduct = New With {Key productName, Key productPrice} ' To create uppercase variable names for the new properties, ' assign variables productName and productPrice to uppercase identifiers. Dim anonProduct1 = New With {Key .Name = productName, Key .Price = productPrice}
从其他对象的属性或字段名称。 例如,考虑包含
car
和CarClass
属性的Name
类型的ID
对象。 若要创建一个匿名类型实例car1
,并且其Name
和ID
属性使用car
对象的值进行初始化,则可以编写下面的代码:Dim car1 = New With {Key car.Name, Key car.ID}
以上声明等效于定义匿名类型
car2
的一行较长的代码。Dim car2 = New With {Key .Name = car.Name, Key .ID = car.ID}
从 XML 成员名称。
Dim books = <Books> <Book Author="Jesper Aaberg"> Advanced Programming Methods </Book> </Books> Dim anon = New With {books...<Book>}
为
anon
产生的类型将具有一个属性Book
,其类型为 IEnumerable(Of XElement)。从没有参数的函数,例如下面示例中的
SomeFunction
。Dim sc As New SomeClass Dim anon1 = New With {Key sc.SomeFunction()}
下面代码中的变量
anon2
是具有一个属性(一个名为First
的字符)的匿名类型。 这段代码将显示函数 First返回的字母“E”。Dim aString As String = "Example String" Dim anon2 = New With {Key aString.First()} ' The variable anon2 has one property, First. Console.WriteLine(anon2.First)
推理失败
名称推理在许多情况下将失败,包括:
推理派生自对方法、构造函数或需要参数的参数化属性的调用。 如果
anon1
具有一个或多个参数,则上面的someFunction
声明将失败。' Not valid. ' Dim anon3 = New With {Key sc.someFunction(someArg)}
向新属性名赋值可以解决这一问题。
' Valid. Dim anon4 = New With {Key .FunResult = sc.someFunction(someArg)}
推理派生自复杂表达式。
Dim aString As String = "Act " ' Not valid. ' Dim label = New With {Key aString & "IV"}
将表达式的结果赋给属性名可以消除此错误。
' Valid. Dim label1 = New With {Key .someLabel = aString & "IV"}
对多个属性的推理会产生两个或更多的同名属性。 回到前面示例中的声明,在那些声明中,不能将
product.Name
和car1.Name
同时列为同一匿名类型的属性。 这是因为这些属性的推断标识符都是Name
。' Not valid. ' Dim anon5 = New With {Key product.Name, Key car1.Name}
通过为不同属性名赋值可以解决此问题。
' Valid. Dim anon6 = New With {Key .ProductName = product.Name, Key .CarName = car1.Name}
请注意,更改大小写(在大写和小写字母之间切换)不能区分两个名称。
Dim price = 0 ' Not valid, because Price and price are the same name. ' Dim anon7 = New With {Key product.Price, Key price}
属性的初始类型和值取决于尚未建立的另一个属性。 例如,
.IDName = .LastName
在匿名类型声明中无效,除非.LastName
已经初始化。' Not valid. ' Dim anon8 = New With {Key .IDName = .LastName, Key .LastName = "Jones"}
在此示例中,可以通过逆转声明属性的顺序来解决问题。
' Valid. Dim anon9 = New With {Key .LastName = "Jones", Key .IDName = .LastName}
匿名类型的属性名和 Object的成员的名称相同。 例如,因为
Equals
是 Object的一个方法,所以下面的声明会失败。' Not valid. ' Dim relationsLabels1 = New With {Key .Equals = "equals", Key .Greater = _ ' "greater than", Key .Less = "less than"}
可以通过更改属性名来修复该问题:
' Valid Dim relationsLabels2 = New With {Key .EqualString = "equals", Key .GreaterString = "greater than", Key .LessString = "less than"}