How to: Infer Property Names and Types in Anonymous Type Declarations (Visual Basic)

Anonymous types provide no mechanism for directly specifying the data types of properties. Types of all properties are inferred. In the following example, the types of Name and Price are inferred directly from the values that are used to initialize them.

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

Anonymous types can also infer property names and types from other sources. The sections that follow provide a list of the circumstances where inference is possible, and examples of situations where it is not.

Successful Inference

Anonymous types can infer property names and types from the following sources:

  • From variable names. Anonymous type anonProduct will have two properties, productName and productPrice. Their data types will be those of the original variables, String and Double, respectively.

    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}
    
  • From property or field names of other objects. For example, consider a car object of a CarClass type that includes Name and ID properties. To create a new anonymous type instance, car1, with Name and ID properties that are initialized with the values from the car object, you can write the following:

    Dim car1 = New With {Key car.Name, Key car.ID}
    

    The previous declaration is equivalent to the longer line of code that defines anonymous type car2.

    Dim car2 = New With {Key .Name = car.Name, Key .ID = car.ID}
    
  • From XML member names.

    Dim books = <Books>
                    <Book Author="Jesper Aaberg">
                        Advanced Programming Methods
                    </Book>
                </Books>
    Dim anon = New With {books...<Book>}
    

    The resulting type for anon would have one property, Book, of type IEnumerable(Of XElement).

  • From a function that has no parameters, such as SomeFunction in the following example.

    Dim sc As New SomeClass
    Dim anon1 = New With {Key sc.SomeFunction()}
    

    The variable anon2 in the following code is an anonymous type that has one property, a character named First. This code will display a letter "E," the letter that is returned by function 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)
    

Inference Failures

Name inference will fail in many circumstances, including the following:

  • The inference derives from the invocation of a method, a constructor, or a parameterized property that requires arguments. The previous declaration of anon1 fails if someFunction has one or more arguments.

    ' Not valid.
    ' Dim anon3 = New With {Key sc.someFunction(someArg)}
    

    Assignment to a new property name solves the problem.

    ' Valid.
    Dim anon4 = New With {Key .FunResult = sc.someFunction(someArg)}
    
  • The inference derives from a complex expression.

    Dim aString As String = "Act "
    ' Not valid.
    ' Dim label = New With {Key aString & "IV"}
    

    The error can be resolved by assigning the result of the expression to a property name.

    ' Valid.
    Dim label1 = New With {Key .someLabel = aString & "IV"}
    
  • Inference for multiple properties produces two or more properties that have the same name. Referring back to declarations in earlier examples, you cannot list both product.Name and car1.Name as properties of the same anonymous type. This is because the inferred identifier for each of these would be Name.

    ' Not valid.
    ' Dim anon5 = New With {Key product.Name, Key car1.Name}
    

    The problem can be solved by assigning the values to distinct property names.

    ' Valid.
    Dim anon6 = New With {Key .ProductName = product.Name, Key .CarName = car1.Name}
    

    Note that changes in case (changes between uppercase and lowercase letters) do not make two names distinct.

    Dim price = 0
    ' Not valid, because Price and price are the same name.
    ' Dim anon7 = New With {Key product.Price, Key price}
    
  • The initial type and value of one property depends on another property that is not yet established. For example, .IDName = .LastName is not valid in an anonymous type declaration unless .LastName is already initialized.

    ' Not valid.
    ' Dim anon8 = New With {Key .IDName = .LastName, Key .LastName = "Jones"}
    

    In this example, you can fix the problem by reversing the order in which the properties are declared.

    ' Valid.
    Dim anon9 = New With {Key .LastName = "Jones", Key .IDName = .LastName}
    
  • A property name of the anonymous type is the same as the name of a member of Object. For example, the following declaration fails because Equals is a method of Object.

    ' Not valid.
    ' Dim relationsLabels1 = New With {Key .Equals = "equals", Key .Greater = _
    '                       "greater than", Key .Less = "less than"}
    

    You can fix the problem by changing the property name:

    ' Valid 
    Dim relationsLabels2 = New With {Key .EqualString = "equals",
                                     Key .GreaterString = "greater than",
                                     Key .LessString = "less than"}
    

See also