Tipos anónimos (Visual Basic)Anonymous Types (Visual Basic)

Visual Basic admite los tipos anónimos, lo que le permite crear objetos sin escribir una definición de clase para el tipo de datos.Visual Basic supports anonymous types, which enable you to create objects without writing a class definition for the data type. En su lugar, el compilador genera una clase.Instead, the compiler generates a class for you. La clase no tiene ningún nombre utilizable, hereda directamente de Objecty contiene las propiedades especificadas al declarar el objeto.The class has no usable name, inherits directly from Object, and contains the properties you specify in declaring the object. Dado que no se especifica el nombre del tipo de datos, se conoce como un tipo anónimo.Because the name of the data type is not specified, it is referred to as an anonymous type.

El ejemplo siguiente declara y crea la variable product como una instancia de un tipo anónimo que tiene dos propiedades, Name y Price.The following example declares and creates variable product as an instance of an anonymous type that has two properties, Name and Price.

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

Un expresión de consulta usa tipos anónimos para combinar las columnas de datos seleccionados por una consulta.A query expression uses anonymous types to combine columns of data selected by a query. No se puede definir el tipo del resultado de antemano, porque no se puede predecir las columnas que se puede seleccionar una consulta determinada.You cannot define the type of the result in advance, because you cannot predict the columns a particular query might select. Tipos anónimos permiten escribir una consulta que selecciona cualquier número de columnas, en cualquier orden.Anonymous types enable you to write a query that selects any number of columns, in any order. El compilador crea un tipo de datos que coincida con las propiedades especificadas y el orden especificado.The compiler creates a data type that matches the specified properties and the specified order.

En los ejemplos siguientes, products es una lista de objetos de producto, cada uno de los cuales tiene muchas propiedades.In the following examples, products is a list of product objects, each of which has many properties. Variable namePriceQuery contiene la definición de una consulta que, cuando se ejecuta, devuelve una colección de instancias de un tipo anónimo que tiene dos propiedades, Name y Price.Variable namePriceQuery holds the definition of a query that, when it is executed, returns a collection of instances of an anonymous type that has two properties, Name and Price.

Dim namePriceQuery = From prod In products
                     Select prod.Name, prod.Price

Variable nameQuantityQuery contiene la definición de una consulta que, cuando se ejecuta, devuelve una colección de instancias de un tipo anónimo que tiene dos propiedades, Name y OnHand.Variable nameQuantityQuery holds the definition of a query that, when it is executed, returns a collection of instances of an anonymous type that has two properties, Name and OnHand.

Dim nameQuantityQuery = From prod In products
                        Select prod.Name, prod.OnHand

Para obtener más información sobre el código creado por el compilador para un tipo anónimo, vea Anonymous Type Definition.For more information about the code created by the compiler for an anonymous type, see Anonymous Type Definition.

Precaución

El nombre del tipo anónimo es el compilador genera y puede variar de una compilación a otra.The name of the anonymous type is compiler generated and may vary from compilation to compilation. El código no debe utilizar o se basan en el nombre de un tipo anónimo porque el nombre podría cambiar cuando se vuelve a compilar un proyecto.Your code should not use or rely on the name of an anonymous type because the name might change when a project is recompiled.

Declarar un tipo anónimoDeclaring an Anonymous Type

La declaración de una instancia de un tipo anónimo usa una lista de inicializadores para especificar las propiedades del tipo.The declaration of an instance of an anonymous type uses an initializer list to specify the properties of the type. Puede especificar solo las propiedades cuando se declaran un tipo anónimo, no otros elementos de clase como métodos o eventos.You can specify only properties when you declare an anonymous type, not other class elements such as methods or events. En el ejemplo siguiente, product1 es una instancia de un tipo anónimo que tiene dos propiedades: Name y Price.In the following example, product1 is an instance of an anonymous type that has two properties: Name and Price.

' Variable product1 is an instance of a simple anonymous type.
Dim product1 = New With {.Name = "paperclips", .Price = 1.29}
' -or-
' product2 is an instance of an anonymous type with key properties.
Dim product2 = New With {Key .Name = "paperclips", Key .Price = 1.29}

Si las propiedades se designan como propiedades de clave, se puede usar para comparar dos instancias de tipo anónimo son iguales.If you designate properties as key properties, you can use them to compare two anonymous type instances for equality. Sin embargo, no se puede cambiar los valores de las propiedades de clave.However, the values of key properties cannot be changed. Consulte la sección de propiedades de clave más adelante en este tema para obtener más información.See the Key Properties section later in this topic for more information.

Tenga en cuenta que declarar una instancia de un tipo anónimo es como la declaración de una instancia de un tipo con nombre mediante el uso de un inicializador de objeto:Notice that declaring an instance of an anonymous type is like declaring an instance of a named type by using an object initializer:

' Variable product3 is an instance of a class named Product.
Dim product3 = New Product With {.Name = "paperclips", .Price = 1.29}

Para obtener más información sobre otras maneras de especificar las propiedades de tipo anónimo, vea Cómo: Deducir tipos y nombres de propiedad en declaraciones de tipos anónimos.For more information about other ways to specify anonymous type properties, see How to: Infer Property Names and Types in Anonymous Type Declarations.

Propiedades claveKey Properties

Propiedades de clave se diferencian de las propiedades que no son de clave de varias maneras fundamentales:Key properties differ from non-key properties in several fundamental ways:

  • Solo los valores de las propiedades de clave se comparan con el fin de determinar si dos instancias son iguales.Only the values of key properties are compared in order to determine whether two instances are equal.

  • Los valores de las propiedades clave son de solo lectura y no se puede cambiar.The values of key properties are read-only and cannot be changed.

  • Solo se incluyen los valores de propiedad de clave en el algoritmo de código hash generado por el compilador para un tipo anónimo.Only key property values are included in the compiler-generated hash code algorithm for an anonymous type.

IgualdadEquality

Instancias de tipos anónimos pueden ser iguales solo si son instancias del mismo tipo anónimo.Instances of anonymous types can be equal only if they are instances of the same anonymous type. El compilador trata las dos instancias como instancias del mismo tipo si cumplen las condiciones siguientes:The compiler treats two instances as instances of the same type if they meet the following conditions:

  • Se declaran en el mismo ensamblado.They are declared in the same assembly.

  • Sus propiedades tienen los mismos nombres, los mismos tipos deducidos y se declaran en el mismo orden.Their properties have the same names, the same inferred types, and are declared in the same order. Las comparaciones de nombres no distinguen mayúsculas de minúsculas.Name comparisons are not case-sensitive.

  • Las mismas propiedades en cada una se marcan como propiedades de clave.The same properties in each are marked as key properties.

  • Al menos una propiedad en cada declaración es una propiedad clave.At least one property in each declaration is a key property.

Una instancia de un tipo anónimo que no tiene ninguna propiedad clave es igual solo a sí mismo.An instance of an anonymous types that has no key properties is equal only to itself.

' prod1 and prod2 have no key values.
Dim prod1 = New With {.Name = "paperclips", .Price = 1.29}
Dim prod2 = New With {.Name = "paperclips", .Price = 1.29}

' The following line displays False, because prod1 and prod2 have no
' key properties.
Console.WriteLine(prod1.Equals(prod2))

' The following statement displays True because prod1 is equal to itself.
Console.WriteLine(prod1.Equals(prod1))

Dos instancias del mismo tipo anónimo son iguales si los valores de sus propiedades clave son iguales.Two instances of the same anonymous type are equal if the values of their key properties are equal. Los ejemplos siguientes muestran cómo se comprueba la igualdad.The following examples illustrate how equality is tested.

Dim prod3 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod4 = New With {Key .Name = "paperclips", Key .Price = 1.29}
' The following line displays True, because prod3 and prod4 are
' instances of the same anonymous type, and the values of their
' key properties are equal.
Console.WriteLine(prod3.Equals(prod4))

Dim prod5 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod6 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays False, because prod5 and prod6 do not 
' have the same properties.
Console.WriteLine(prod5.Equals(prod6))

Dim prod7 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 24}
Dim prod8 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays True, because prod7 and prod8 are
' instances of the same anonymous type, and the values of their
' key properties are equal. The equality check does not compare the
' values of the non-key field.
Console.WriteLine(prod7.Equals(prod8))

Valores de solo lecturaRead-Only Values

No se puede cambiar los valores de las propiedades de clave.The values of key properties cannot be changed. Por ejemplo, en prod8 en el ejemplo anterior, el Name y Price campos son read-only, pero OnHand puede cambiarse.For example, in prod8 in the previous example, the Name and Price fields are read-only, but OnHand can be changed.

' The following statement will not compile, because Name is a key
' property and its value cannot be changed.
' prod8.Name = "clamps"

' OnHand is not a Key property. Its value can be changed.
prod8.OnHand = 22

Tipos anónimos desde las expresiones de consultaAnonymous Types from Query Expressions

Las expresiones de consulta no siempre requieren la creación de tipos anónimos.Query expressions do not always require the creation of anonymous types. Cuando sea posible, usan un tipo existente para almacenar los datos de columna.When possible, they use an existing type to hold the column data. Esto se produce cuando la consulta devuelve los registros completos desde el origen de datos o solo un campo de cada registro.This occurs when the query returns either whole records from the data source, or only one field from each record. En los siguientes ejemplos de código, customers es una colección de objetos de un Customer clase.In the following code examples, customers is a collection of objects of a Customer class. La clase tiene muchas propiedades y puede incluir uno o varios de ellos en el resultado de consulta, en cualquier orden.The class has many properties, and you can include one or more of them in the query result, in any order. En los dos primeros ejemplos, no hay tipos anónimos son necesarios porque las consultas seleccionan elementos de tipos con nombre:In the first two examples, no anonymous types are required because the queries select elements of named types:

  • custs1 contiene una colección de cadenas, porque cust.Name es una cadena.custs1 contains a collection of strings, because cust.Name is a string.

    Dim custs1 = From cust In customers
                 Select cust.Name
    
  • custs2 contiene una colección de Customer objetos, ya que cada elemento de customers es un Customer objeto y todo el elemento se selecciona la consulta.custs2 contains a collection of Customer objects, because each element of customers is a Customer object, and the whole element is selected by the query.

    Dim custs2 = From cust In customers
                 Select cust
    

Sin embargo, no siempre están disponibles los tipos con nombre apropiados.However, appropriate named types are not always available. Es posible que desee seleccionar nombres de los clientes y direcciones para un propósito, números de Id. de cliente y las ubicaciones de otra y los nombres de cliente, direcciones y los historiales de orden para una tercera.You might want to select customer names and addresses for one purpose, customer ID numbers and locations for another, and customer names, addresses, and order histories for a third. Tipos anónimos permiten seleccionar cualquier combinación de propiedades, en cualquier orden, sin declarar primero un nuevo tipo con nombre para contener el resultado.Anonymous types enable you to select any combination of properties, in any order, without first declaring a new named type to hold the result. En su lugar, el compilador crea un tipo anónimo para cada compilación de propiedades.Instead, the compiler creates an anonymous type for each compilation of properties. La consulta siguiente selecciona solo el cliente nombre y número de identificación de cada Customer objeto customers.The following query selects only the customer's name and ID number from each Customer object in customers. Por lo tanto, el compilador crea un tipo anónimo que contenga sólo esas dos propiedades.Therefore, the compiler creates an anonymous type that contains only those two properties.

Dim custs3 = From cust In customers
             Select cust.Name, cust.ID

Los nombres y los tipos de datos de las propiedades del tipo anónimo se toman de los argumentos de Select, cust.Name y cust.ID.Both the names and the data types of the properties in the anonymous type are taken from the arguments to Select, cust.Name and cust.ID. Las propiedades de un tipo anónimo creado por una consulta siempre son las propiedades de clave.The properties in an anonymous type that is created by a query are always key properties. Cuando custs3 se ejecuta en el siguiente For Each bucle, el resultado es una colección de instancias de un tipo anónimo con dos propiedades de clave, Name y ID.When custs3 is executed in the following For Each loop, the result is a collection of instances of an anonymous type with two key properties, Name and ID.

For Each selectedCust In custs3
    Console.WriteLine(selectedCust.ID & ": " & selectedCust.Name)
Next

Los elementos de la colección representada por custs3 están fuertemente tipados, y puede usar IntelliSense para navegar por las propiedades disponibles y comprobar sus tipos.The elements in the collection represented by custs3 are strongly typed, and you can use IntelliSense to navigate through the available properties and to verify their types.

Para obtener más información, consulte Introducción a LINQ en Visual Basic.For more information, see Introduction to LINQ in Visual Basic.

Decidir entre usar tipos anónimosDeciding Whether to Use Anonymous Types

Antes de crear un objeto como una instancia de una clase anónima, tenga en cuenta si es la mejor opción.Before you create an object as an instance of an anonymous class, consider whether that is the best option. Por ejemplo, si desea crear un objeto temporal para contener datos relacionados, y no es necesario para otros campos y métodos que puede contener una clase completa, un tipo anónimo es una buena solución.For example, if you want to create a temporary object to contain related data, and you have no need for other fields and methods that a complete class might contain, an anonymous type is a good solution. Tipos anónimos también resultan prácticos si desea una selección diferente de propiedades para cada declaración, o si desea cambiar el orden de las propiedades.Anonymous types are also convenient if you want a different selection of properties for each declaration, or if you want to change the order of the properties. Sin embargo, si el proyecto incluye varios objetos que tienen las mismas propiedades, en un orden fijo, se pueden declarar más fácilmente mediante el uso de un tipo con nombre con un constructor de clase.However, if your project includes several objects that have the same properties, in a fixed order, you can declare them more easily by using a named type with a class constructor. Por ejemplo, con un constructor adecuado, es más fácil declarar varias instancias de un Product clase que es declarar varias instancias de un tipo anónimo.For example, with an appropriate constructor, it is easier to declare several instances of a Product class than it is to declare several instances of an anonymous type.

' Declaring instances of a named type.
Dim firstProd1 As New Product("paperclips", 1.29)
Dim secondProd1 As New Product("desklamp", 28.99)
Dim thirdProd1 As New Product("stapler", 5.09)

' Declaring instances of an anonymous type.
Dim firstProd2 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim secondProd2 = New With {Key .Name = "desklamp", Key .Price = 28.99}
Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = 5.09}

Otra ventaja de tipos con nombre es que el compilador puede detectar un error ortográfico accidental de un nombre de propiedad.Another advantage of named types is that the compiler can catch an accidental mistyping of a property name. En los ejemplos anteriores, firstProd2, secondProd2, y thirdProd2 están diseñados para ser instancias del mismo tipo anónimo.In the previous examples, firstProd2, secondProd2, and thirdProd2 are intended to be instances of the same anonymous type. Sin embargo, si tuviera que accidentalmente declarar thirdProd2 en una de las siguientes maneras, su tipo sería diferente de firstProd2 y secondProd2.However, if you were to accidentally declare thirdProd2 in one of the following ways, its type would be different from that of firstProd2 and secondProd2.

' Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = 5.09}
' Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = "5.09"}
' Dim thirdProd2 = New With {Key .Name = "stapler", .Price = 5.09}

Más importante aún, hay limitaciones en el uso de tipos anónimos que no se aplican a las instancias de tipos con nombre.More importantly, there are limitations on the use of anonymous types that do not apply to instances of named types. firstProd2, secondProd2, y thirdProd2 son instancias del mismo tipo anónimo.firstProd2, secondProd2, and thirdProd2 are instances of the same anonymous type. Sin embargo, el nombre del tipo anónimo compartido no está disponible y no puede aparecer donde se espera un nombre de tipo en el código.However, the name for the shared anonymous type is not available and cannot appear where a type name is expected in your code. Por ejemplo, un tipo anónimo no se puede usar para definir una firma de método para declarar otra variable o campo o en cualquier declaración de tipo.For example, an anonymous type cannot be used to define a method signature, to declare another variable or field, or in any type declaration. Como resultado, los tipos anónimos no son adecuados cuando tiene que compartir información a través de métodos.As a result, anonymous types are not appropriate when you have to share information across methods.

Una definición de tipo anónimoAn Anonymous Type Definition

En respuesta a la declaración de una instancia de un tipo anónimo, el compilador crea una nueva definición de clase que contiene las propiedades especificadas.In response to the declaration of an instance of an anonymous type, the compiler creates a new class definition that contains the specified properties.

Si el tipo anónimo contiene al menos una propiedad clave, la definición invalida tres miembros heredados de Object: Equals, GetHashCode, y ToString.If the anonymous type contains at least one key property, the definition overrides three members inherited from Object: Equals, GetHashCode, and ToString. El código generado para comprobar la igualdad y determinar que el valor del código hash tiene en cuenta solo las propiedades de clave.The code produced for testing equality and determining the hash code value considers only the key properties. Si el tipo anónimo no contiene ninguna propiedad clave, solo ToString se reemplaza.If the anonymous type contains no key properties, only ToString is overridden. Propiedades con nombre explícito de un tipo anónimo no pueden entrar en conflicto con estos métodos generados.Explicitly named properties of an anonymous type cannot conflict with these generated methods. Es decir, no puede usar .Equals, .GetHashCode, o .ToString a una propiedad de nombre.That is, you cannot use .Equals, .GetHashCode, or .ToString to name a property.

Las definiciones de tipo anónimo que tengan al menos una propiedad de clave también implementan la System.IEquatable<T> interfaz, donde T es el tipo del tipo anónimo.Anonymous type definitions that have at least one key property also implement the System.IEquatable<T> interface, where T is the type of the anonymous type.

Para obtener más información sobre el código creado por el compilador y la funcionalidad de los métodos invalidados, vea Anonymous Type Definition.For more information about the code created by the compiler and the functionality of the overridden methods, see Anonymous Type Definition.

Vea tambiénSee also