如何:推断匿名类型声明中的属性名称和类型 (Visual Basic)

匿名类型不提供直接指定属性数据类型的机制。 推断出所有属性的类型。 在下面的示例中,NamePrice 的类型是从用于初始化它们的值中直接推断出来的。

' Variable product is an instance of a simple anonymous type.
Dim product = New With {Key .Name = "paperclips", .Price = 1.29}

匿名类型还可以从其他源推断属性名称和类型。 以下各部分提供推理可能的情况列表,以及不存在的情况示例。

成功推理

匿名类型可以从以下源推断属性名称和类型:

  • 从变量名称。 匿名类型 anonProduct 将具有两个属性, productName 以及 productPrice。 它们的数据类型将分别为原始变量StringDouble的数据类型。

    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类型,并且包含NameID属性。 若要创建新的匿名类型实例car1,其属性NameID是用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字符。 此代码将显示字母“E”,该字母由函数 First返回。

    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.Namecar1.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的名称相同。 例如,以下声明失败,因为 EqualsObject 的一个方法。

    ' 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"}
    

另请参阅