C# - Tipos Anônimos (Anonymous Types)


Os tipos anônimos fornecem uma maneira conveniente para encapsular um conjunto de propriedades somente leitura em um único objeto sem precisar primeiro definir explicitamente um tipo.

O nome do tipo é gerado pelo compilador e não está disponível no nível do código fonte. O tipo das propriedades é inferido pelo compilador.

O exemplo a seguir mostra um tipo anônimo sendo inicializado com 3 propriedades chamadas id, preco e nome.

Abra o Visual C# 2010 Express Edition e crie um novo projeto do tipo Console Application com o nome TiposAnonimos e a seguir digite o código abaixo:

using System;

namespace TiposAnonimos
{
    class Program
    {
        static void Main(string[] args)
        {
            var produto = new
            {
                id = 1,
                nome = "Monitor LED 32 polegadas",
                preco = 1500
            };
            Console.WriteLine("id: {0} {1} - preço: {2:n2}", produto.id, produto.nome, produto.preco);
            Console.Readkey();
        }
    }
}

Você vai conseguir compilar e rodar o projeto com sucesso e verá o resultado exibido no console conforme a figura ao lado.

Agora eu pergunto: Onde esta a classe produto ?

Percebeu que criamos um tipo, definimos 3 propriedades e atribuímos valores a elas e acessamos esses valores exibindo-os no console sem ter que criar a classe e depois a sua instância ?

É justamente isso que são os tipos anônimos.

Mas onde eu utilizo esse recurso ?

Tipos anônimos são normalmente usados em uma cláusula Select de uma expressão de consulta, geralmente com LINQ, para retornar um subconjunto das propriedades de cada objeto na seqüência de origem.

Como eu crio os tipos anônimos ?

Tipos anônimos são criados usando operador new com um inicializador de objeto.

O cenário mais comum é inicializar um tipo anônimo com algumas propriedades de outro tipo. No exemplo a seguir, suponha que uma classe chamada Produto que inclui as propriedades Id, Nome e Descricao. No exemplo produtos é uma coleção de objetos Produto.

using System;
using System.Collections.Generic;
using System.Linq;

namespace C_TipoAnonimos
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Produto> produtos = new List<Produto>();
            Produto produto = new Produto();
            produto.Id = 1;
            produto.Nome = "Mouse Microsoft";
            produto.Descricao = "Mouse sem fio 1200 dpi";
            produto.Estoque = 10;
            produtos.Add(produto);

            produto = new Produto();
            produto.Id = 2;
            produto.Nome = "Fone Ouvidos State Lite";
            produto.Descricao = "Fone de ouvidos de luxo";
            produto.Estoque = 5;
            produtos.Add(produto);
            var consultaProduto = from prod in produtos
                                              select new { prod.Id, prod.Nome, prod.Descricao };

            foreach (var p in consultaProduto)
            {
                Console.WriteLine("Id={0}, Nome={1}, Descricao={2} ", p.Id, p.Nome, p.Descricao);
            }

        }
    }
    class Produto
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Descricao { get; set; }
        public int Estoque { get; set; }
    }
}
Criamos um novo tipo de dados com duas propriedades Id e Nome; Na utilização veremos que o Intellisense exibe apenas essas duas propriedades; Isso nos fornece a segurança de tipos;

A declaração de tipo anônimo começa com palavra-chave new e inicializa um novo tipo que usa apenas duas propriedades, Id e Nome, do Produto. Isso faz com que uma quantidade menor de dados sejam retornados na consulta.

Se você não especificar os nomes de membro no tipo anônimo, o compilador dá aos membros do tipo anônimo o mesmo nome que a propriedade que está sendo usada para inicializá-las. Você deve fornecer um nome para a propriedade que está sendo inicializada com uma expressão.

Tipos anônimos são os tipos de referência que derivam diretamente de object. O compilador dá a eles um nome embora sua aplicação não possa acessá-lo. Da perspectiva do common language runtime, um tipo anônimo não é diferente de qualquer outro tipo de referência, exceto que ele não pode ser convertido para qualquer tipo exceto object.

Se dois ou mais tipos anônimos tiverem o mesmo número e tipo de propriedades na mesma ordem, o compilador irá tratá-los como o mesmo tipo e eles compartilham as mesmas informações de tipo gerado pelo compilador.

Um tipo anônimo tem o escopo do método. Para passar um tipo anônimo ou uma coleção que contém os tipos anônimos, fora dos limites de um método, você deve converter primeiramente o tipo para object. No entanto, isso anula a tipagem forte do tipo anônimo. Se você precisar armazenar os resultados de suas consultas ou passá-las fora dos limites de método, considere o uso de uma classe ou struct em vez de um tipo anônimo.

Propriedades de tipos anônimos não podem conter tipos ponteiro.

Como os métodos Equals e GetHashCode nos tipos anônimos são definidos em termos das propriedades Equals e GetHashcode , duas instâncias do mesmo tipo anônimo serão iguais, apenas se todas as suas propriedades forem iguais.

Lembre-se que um tipo anônimo é imutável pois todas as suas propriedades são somente leitura.

Rom 10:12 Porquanto não há distinção entre judeu e grego; porque o mesmo Senhor o é de todos, rico para com todos os que o invocam.
Rom 10:13
Porque: Todo aquele que invocar o nome do Senhor será salvo.

Referências:


José Carlos Macoratti