Inicializadores de objetos: Tipos con nombre y anónimos (Visual Basic)

Los inicializadores de objetos permiten especificar propiedades para un objeto complejo mediante una sola expresión. Se pueden usar para crear instancias de tipos con nombre y de tipos anónimos.

Declaraciones

Las declaraciones de instancias de tipos con nombre y anónimos pueden tener un aspecto casi idéntico, pero sus efectos no son los mismos. Cada categoría tiene capacidades y restricciones propias. En el ejemplo siguiente se muestra una manera idónea de declarar e inicializar una instancia de una clase con nombre, Customer, mediante una lista de inicializadores de objetos. Observe que el nombre de la clase se especifica después de la palabra clave New.

Dim namedCust = New Customer With {.Name = "Terry Adams"}

Un tipo anónimo no tiene ningún nombre utilizable. Por lo tanto, la creación de una instancia de un tipo anónimo no puede incluir un nombre de clase.

Dim anonymousCust = New With {.Name = "Hugo Garcia"}

Los requisitos y los resultados de las dos declaraciones no son los mismos. Para namedCust, una clase Customer que tiene una propiedad Name ya debe estar presente, y la declaración crea una instancia de esa clase. Para anonymousCust, el compilador define una nueva clase que tiene una propiedad, una cadena denominada Name, y crea una nueva instancia de esa clase.

Tipos con nombre

Los inicializadores de objetos proporcionan una manera sencilla de llamar al constructor de un tipo y, después, de establecer los valores de algunas o todas las propiedades en una sola instrucción. El compilador invoca el constructor adecuado para la instrucción: el constructor sin parámetros si no se presentan argumentos o un constructor parametrizado si se envían uno o varios argumentos. Después, las propiedades especificadas se inicializan en el orden en que se presentan en la lista de inicializadores.

Cada inicialización de la lista de inicializadores consta de la asignación de un valor inicial a un miembro de la clase. Los nombres y los tipos de datos de los miembros se determinan cuando se define la clase. En los ejemplos siguientes, la clase Customer debe existir y debe tener miembros denominados Name y City, que puedan aceptar valores de cadena.

Dim cust0 As Customer = New Customer With {.Name = "Toni Poe", 
                                           .City = "Louisville"}

Como alternativa, puede obtener el mismo resultado mediante el código siguiente:

Dim cust1 As New Customer With {.Name = "Toni Poe", 
                                .City = "Louisville"}

Cada una de estas declaraciones es equivalente al ejemplo siguiente, que crea un objeto Customer mediante el constructor sin parámetros y, después, especifica los valores iniciales de las propiedades Name y City mediante una instrucción With.

Dim cust2 As New Customer()
With cust2
    .Name = "Toni Poe"
    .City = "Louisville"
End With

Si la clase Customer contiene un constructor parametrizado que le permite enviar un valor para Name, por ejemplo, también puede declarar e inicializar un objeto Customer de las maneras siguientes:

Dim cust3 As Customer = 
    New Customer("Toni Poe") With {.City = "Louisville"}
' --or--
Dim cust4 As New Customer("Toni Poe") With {.City = "Louisville"}

No es necesario inicializar todas las propiedades, como se muestra en el código siguiente.

Dim cust5 As Customer = New Customer With {.Name = "Toni Poe"}

Sin embargo, la lista de inicialización no puede estar vacía. Las propiedades sin inicializar conservan sus valores predeterminados.

Inferencia de tipos en los tipos con nombre

Puede acortar el código para la declaración de cust1 mediante la combinación de inicializadores de objetos y la inferencia de tipos locales. Esto le permite omitir la cláusula As en la declaración de la variable. El tipo de datos de la variable se infiere del tipo del objeto creado por la asignación. En el ejemplo siguiente, el tipo de cust6 es Customer.

Dim cust6 = New Customer With {.Name = "Toni Poe", 
                               .City = "Louisville"}

Comentarios sobre los tipos con nombre

  • Un miembro de clase no se puede inicializar más de una vez en la lista de inicializadores de objetos. La declaración de cust7 provoca un error.

    '' This code does not compile because Name is initialized twice.
    ' Dim cust7 = New Customer With {.Name = "Toni Poe", 
    '                                .City = "Louisville",
    '                                .Name = "Blue Yonder Airlines"}
    
  • Un miembro se puede usar para inicializarse a sí mismo u a otro campo. Si se accede a un miembro antes de que se haya inicializado, como en la siguiente declaración para cust8, se usará el valor predeterminado. Recuerde que, cuando se procesa una declaración que usa un inicializador de objetos, lo primero que sucede es que se invoca el constructor adecuado. Después, se inicializan los campos individuales de la lista de inicializadores. En los ejemplos siguientes, se asigna el valor predeterminado de Name para cust8 y se asigna un valor inicializado en cust9.

    Dim cust8 = New Customer With {.Name = .Name & ", President"}
    Dim cust9 = New Customer With {.Name = "Toni Poe", 
                                   .Title = .Name & ", President"}
    

    En el ejemplo siguiente se usa el constructor parametrizado de cust3 y cust4 para declarar e inicializar cust10 y cust11.

    Dim cust10 = New Customer("Toni Poe") With {.Name = .Name & ", President"}
    ' --or--
    Dim cust11 As New Customer("Toni Poe") With {.Name = .Name & ", President"}
    
  • Los inicializadores de objetos se pueden anidar. En el ejemplo siguiente, AddressClass es una clase que tiene dos propiedades, City y State, y la clase Customer tiene una propiedad Address que es una instancia de AddressClass.

    Dim cust12 = 
        New Customer With {.Name = "Toni Poe", 
                           .Address = 
                               New AddressClass With {.City = "Louisville", 
                                                      .State = "Kentucky"}}
    Console.WriteLine(cust12.Address.State)
    
  • La lista de inicialización no puede estar vacía.

  • La instancia que se inicializa no puede ser de tipo Object.

  • Los miembros de clase que se inicializan no pueden ser miembros compartidos, miembros de solo lectura, constantes o llamadas de método.

  • Los miembros de clase que se inicializan no se pueden indexar ni calificar. En los ejemplos siguientes se producen errores del compilador:

    '' Not valid.

    ' Dim c1 = New Customer With {.OrderNumbers(0) = 148662}

    ' Dim c2 = New Customer with {.Address.City = "Springfield"}

Tipos anónimos

Los tipos anónimos usan inicializadores de objetos para crear instancias de tipos nuevos a los que no ha definido ni asignado un nombre explícitamente. En su lugar, el compilador genera un tipo según las propiedades que designe en la lista de inicializadores de objetos. Dado que no se ha especificado el nombre del tipo, se le conoce como un tipo anónimo. Por ejemplo, compare la siguiente declaración con la anterior para cust6.

Dim cust13 = New With {.Name = "Toni Poe", 
                       .City = "Louisville"}

La única diferencia sintáctica es que no se especifica ningún nombre después de New para el tipo de datos. Sin embargo, lo que sucede es bastante diferente. El compilador define un nuevo tipo anónimo que tiene dos propiedades, Name y City, y crea una instancia a partir de dicho tipo con los valores especificados. La inferencia de tipos determina los tipos de Name y City en el ejemplo para que sean cadenas.

Precaución

El nombre del tipo anónimo lo genera el compilador y puede variar de compilación a compilación. El código no debe usar ni confiar en el nombre de un tipo anónimo.

Dado que el nombre del tipo no está disponible, no puede usar una cláusula As para declarar cust13. Su tipo debe inferirse. Sin usar el enlace en tiempo de ejecución, el uso de tipos anónimos se limita a las variables locales.

Los tipos anónimos proporcionan compatibilidad crítica con las consultas LINQ. Para más información sobre el uso de tipos anónimos en consultas, consulte Tipos anónimos e Introducción a LINQ en Visual Basic.

Comentarios sobre los tipos anónimos

  • Normalmente, todas o la mayoría de las propiedades de una declaración de tipo anónimo serán propiedades clave, que se indican escribiendo la palabra clave Key delante del nombre de la propiedad.

    
    Dim anonymousCust1 = New With {Key .Name = "Hugo Garcia", 
                                   Key .City = "Louisville"}
    

    Para más información sobre las propiedades clave, consulte Clave.

  • Al igual que los tipos con nombre, las listas de inicializadores para las definiciones de tipos anónimos deben declarar al menos una propiedad.

    Dim anonymousCust = New With {.Name = "Hugo Garcia"}
    
  • Cuando se declara una instancia de un tipo anónimo, el compilador genera una definición de tipo anónimo coincidente. Los nombres y los tipos de datos de las propiedades se toman de la declaración de instancia y los incluye el compilador en la definición. Las propiedades no se denominan y se definen de antemano, como ocurriría con un tipo con nombre. Sus tipos se infieren. No se pueden especificar los tipos de datos de las propiedades mediante una cláusula As.

  • Los tipos anónimos también pueden establecer los nombres y los valores de sus propiedades de otras maneras. Por ejemplo, una propiedad de tipo anónimo puede tomar el nombre y el valor de una variable, o el nombre y el valor de una propiedad de otro objeto.

    ' Create a variable, Name, and give it an initial value.
    Dim Name = "Hugo Garcia"
    
    ' Variable anonymousCust2 will have one property, Name, with 
    ' "Hugo Garcia" as its initial value.
    Dim anonymousCust2 = New With {Key Name}
    
    ' The next declaration uses a property from namedCust, defined
    ' in an earlier example. After the declaration, anonymousCust3 will
    ' have one property, Name, with "Terry Adams" as its value.
    Dim anonymousCust3 = New With {Key namedCust.Name}
    

    Para más información sobre las formas de definir las propiedades de los tipo anónimos, consulte Procedimiento para inferir tipos y nombres de propiedades en declaraciones de tipos anónimos.

Consulte también