Inicializadores de objeto: tipos nomeados e anônimos (Visual Basic)

Os inicializadores de objeto permitem que você especifique propriedades para um objeto complexo usando uma única expressão. Eles podem ser usados para criar instâncias de tipos nomeados e anônimos.

Declarações

Declarações de instâncias de tipos nomeados e anônimos podem parecer quase idênticas, mas seus efeitos são diferentes. Cada categoria tem habilidades e restrições próprias. O exemplo a seguir mostra uma maneira conveniente de declarar e inicializar uma instância de uma classe nomeada Customer, usando uma lista de inicializadores de objeto. Observe que o nome da classe é especificado após a palavra-chave New.

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

Um tipo anônimo não tem nome utilizável. Portanto, uma instanciação de um tipo anônimo não pode incluir um nome de classe.

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

Os requisitos e os resultados das duas declarações não são os mesmos. Para namedCust, uma classe Customer com uma propriedade Name já deve existir e a declaração cria uma instância dessa classe. Para anonymousCust, o compilador define uma nova classe que tem uma propriedade, uma cadeia de caracteres chamada Name e cria uma nova instância dessa classe.

Tipos nomeados

Os inicializadores de objeto fornecem uma maneira simples de chamar o construtor de um tipo e, em seguida, definir os valores de algumas ou todas as propriedades em uma única instrução. O compilador invoca o construtor apropriado para a instrução: o construtor sem parâmetros se nenhum argumento for apresentado ou um construtor parametrizado se um ou mais argumentos forem enviados. Depois disso, as propriedades especificadas são inicializadas na ordem em que são apresentadas na lista de inicializadores.

Cada inicialização na lista de inicializadores consiste na atribuição de um valor inicial para um membro da classe. Os nomes e os tipos de dados dos membros são determinados quando a classe é definida. Nos exemplos a seguir, a classe Customer deve existir e deve ter membros nomeados Name e City que podem aceitar valores de cadeia de caracteres.

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

Como alternativa, você pode obter o mesmo resultado usando o seguinte código:

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

Cada uma dessas declarações é equivalente ao exemplo a seguir, que cria um objeto Customer usando o construtor sem parâmetros e, em seguida, especifica os valores iniciais das propriedades Name e City usando uma instrução With.

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

Se a classe Customer contiver um construtor parametrizado que permite enviar um valor para Name, por exemplo, você também poderá declarar e inicializar um objeto Customer das seguintes maneiras:

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

Você não precisa inicializar todas as propriedades, como mostra o código a seguir.

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

No entanto, a lista de inicialização não pode estar vazia. As propriedades com a inicialização cancelada mantêm seus valores padrão.

Inferência de tipos com tipos nomeados

Você pode reduzir o código da declaração de cust1 combinando inicializadores de objeto e inferência de tipo de variável local. Isso permite omitir a cláusula As na declaração de variável. O tipo de dados da variável é inferido do tipo do objeto que é criado pela atribuição. No exemplo a seguir, o tipo cust6 é Customer.

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

Comentários sobre tipos nomeados

  • Um membro de classe não pode ser inicializado mais de uma vez na lista de inicializadores de objeto. A declaração de cust7 causa um erro.

    '' This code does not compile because Name is initialized twice.
    ' Dim cust7 = New Customer With {.Name = "Toni Poe", 
    '                                .City = "Louisville",
    '                                .Name = "Blue Yonder Airlines"}
    
  • Um membro pode ser usado para inicializar a si mesmo ou outro campo. Se um membro for acessado antes de ser inicializado, como na declaração cust8 a seguir, o valor padrão será usado. Lembre-se de que quando uma declaração que usa um inicializador de objeto é processada, a primeira coisa que acontece é a invocação do construtor apropriado. Depois disso, os campos individuais na lista de inicializadores são inicializados. Nos exemplos a seguir, o valor padrão Name é atribuído para cust8 e um valor inicializado é atribuído em cust9.

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

    O exemplo a seguir usa o construtor parametrizado de cust3 e cust4 para declarar e inicializar cust10 e cust11.

    Dim cust10 = New Customer("Toni Poe") With {.Name = .Name & ", President"}
    ' --or--
    Dim cust11 As New Customer("Toni Poe") With {.Name = .Name & ", President"}
    
  • Os inicializadores de objeto podem ser aninhados. No exemplo a seguir, AddressClass é uma classe com duas propriedades City e State, e a classe Customer tem uma Address propriedade que é uma instância de AddressClass.

    Dim cust12 = 
        New Customer With {.Name = "Toni Poe", 
                           .Address = 
                               New AddressClass With {.City = "Louisville", 
                                                      .State = "Kentucky"}}
    Console.WriteLine(cust12.Address.State)
    
  • A lista de inicialização não pode estar vazia.

  • A instância que está sendo inicializada não pode ser do objeto de tipo.

  • Os membros da classe que estão sendo inicializados não podem ser membros compartilhados, membros somente leitura, constantes ou chamadas de método.

  • Os membros da classe que estão sendo inicializados não podem ser indexados ou qualificados. Os exemplos a seguir geram erros do compilador:

    '' Not valid.

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

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

Tipos anônimos

Tipos anônimos usam inicializadores de objeto para criar instâncias de novos tipos que não são definidas explicitamente e nomeadas. Em vez disso, o compilador gera um tipo de acordo com as propriedades designadas na lista do inicializador de objeto. Como o nome do tipo não é especificado, ele é conhecido como um tipo anônimo. Por exemplo, compare a declaração a seguir com a anterior para cust6.

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

A única diferença sintática é que nenhum nome é especificado depois de New para o tipo de dados. No entanto, o que acontece é bem diferente. O compilador define um novo tipo anônimo que tem duas propriedades Name e City e cria uma instância com os valores especificados. A inferência de tipos determina os tipos Name e City no exemplo como cadeias de caracteres.

Cuidado

O nome do tipo anônimo é gerado pelo compilador e pode variar de compilação para compilação. O código não deve usar nem depender do nome de um tipo anônimo.

Como o nome do tipo não está disponível, não é possível usar uma cláusula As para declarar cust13. Seu tipo deve ser deduzido. Sem usar a associação tardia, isso limita o uso de tipos anônimos a variáveis locais.

Tipos anônimos fornecem suporte crítico a consultas LINQ. Para obter mais informações sobre o uso de tipos anônimos nas consultas, consulte Tipos Anônimos e Introdução ao LINQ no Visual Basic.

Comentários sobre Tipos Anônimos

  • Normalmente, todas ou a maioria das propriedades em uma declaração de tipo anônimo serão de chave, que são indicadas digitando a palavra-chave Key na frente do nome da propriedade.

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

    Para obter mais informações sobre as propriedades de chave, consulte Chave.

  • Como nos tipos nomeados, as listas de inicializadores para definições de tipo anônimo devem declarar pelo menos uma propriedade.

    Dim anonymousCust = New With {.Name = "Hugo Garcia"}
    
  • Quando uma instância de um tipo anônimo é declarada, o compilador gera uma definição de tipo anônimo correspondente. Os nomes e os tipos de dados das propriedades são obtidos da declaração de instância e incluídos pelo compilador na definição. As propriedades não são nomeadas e definidas com antecedência, como ocorreria em um tipo nomeado. Seus tipos são deduzidos. Não é possível especificar os tipos de dados das propriedades usando uma cláusula As.

  • Tipos anônimos também podem estabelecer os nomes e valores das propriedades de várias outras maneiras. Por exemplo, uma propriedade de tipo anônimo pode usar o nome e o valor de uma variável, ou o nome e o valor de uma propriedade de outro 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 obter mais informações sobre as opções de definição de propriedades no tipo anônimo, confira Como inferir nomes e tipos de propriedade em declarações de tipo anônimo.

Confira também