Tipos anónimos
Os tipos anônimos fornecem uma maneira conveniente de encapsular um conjunto de propriedades somente leitura em um único objeto sem ter que definir explicitamente um tipo primeiro. O nome do tipo é gerado pelo compilador e não está disponível no nível do código-fonte. O tipo de cada propriedade é inferido pelo compilador.
Você cria tipos anônimos usando o new
operador junto com um inicializador de objeto. Para obter mais informações sobre inicializadores de objeto, consulte Inicializadores de objeto e coleção.
O exemplo a seguir mostra um tipo anônimo que é inicializado com duas propriedades nomeadas Amount
e Message
.
var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);
Os tipos anônimos são normalmente usados na select
cláusula de uma expressão de consulta para retornar um subconjunto das propriedades de cada objeto na sequência de origem. Para obter mais informações sobre consultas, consulte LINQ em C#.
Os tipos anônimos contêm uma ou mais propriedades públicas somente leitura. Nenhum outro tipo de membro da classe, como métodos ou eventos, é válido. A expressão usada para inicializar uma propriedade não pode ser null
, uma função anônima ou um tipo de ponteiro.
O cenário mais comum é inicializar um tipo anônimo com propriedades de outro tipo. No exemplo a seguir, suponha que existe uma classe chamada Product
. Classe Product
inclui Color
e Price
propriedades, juntamente com outras propriedades que você não está interessado. Variável products
é uma coleção de Product
objetos. A declaração de tipo anónimo começa com a new
palavra-chave. A declaração inicializa um novo tipo que usa apenas duas propriedades de Product
. O uso de tipos anônimos faz com que uma quantidade menor de dados seja retornada na consulta.
Se você não especificar nomes de membros no tipo anônimo, o compilador dará aos membros do tipo anônimo o mesmo nome da propriedade que está sendo usada para inicializá-los. Você fornece um nome para uma propriedade que está sendo inicializada com uma expressão, conforme mostrado no exemplo anterior. No exemplo a seguir, os nomes das propriedades do tipo anônimo são Color
e Price
.
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Gorjeta
Você pode usar a regra de estilo .NET IDE0037 para impor se nomes de membros inferidos ou explícitos são preferidos.
Também é possível definir um campo por objeto de outro tipo: classe, struct ou até mesmo outro tipo anônimo. Isso é feito usando a variável que contém esse objeto, assim como no exemplo a seguir, onde dois tipos anônimos são criados usando tipos definidos pelo usuário já instanciados. Em ambos os casos, o product
campo no tipo shipment
anônimo e shipmentWithBonus
será do tipo Product
contendo seus valores padrão de cada campo. E o bonus
campo será do tipo anônimo criado pelo compilador.
var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };
Normalmente, quando você usa um tipo anônimo para inicializar uma variável, você declara a variável como uma variável local digitada implicitamente usando var. O nome do tipo não pode ser especificado na declaração da variável porque apenas o compilador tem acesso ao nome subjacente do tipo anônimo. Para obter mais informações sobre var
o , consulte Variáveis locais digitadas implicitamente.
Você pode criar uma matriz de elementos digitados anonimamente combinando uma variável local digitada implicitamente e uma matriz digitada implicitamente, conforme mostrado no exemplo a seguir.
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
Tipos anônimos são class
tipos que derivam diretamente de object
, e que não podem ser convertidos para qualquer tipo, exceto object
. O compilador fornece um nome para cada tipo anônimo, embora seu aplicativo não possa acessá-lo. Do ponto de vista do common language runtime, um tipo anônimo não é diferente de qualquer outro tipo de referência.
Se dois ou mais inicializadores de objeto anônimos em um assembly especificarem uma sequência de propriedades que estão na mesma ordem e que têm os mesmos nomes e tipos, o compilador trata os objetos como instâncias do mesmo tipo. Eles compartilham as mesmas informações de tipo geradas pelo compilador.
Os tipos anónimos suportam mutações não destrutivas sob a forma de com expressões. Isso permite que você crie uma nova instância de um tipo anônimo onde uma ou mais propriedades têm novos valores:
var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);
Não é possível declarar um campo, uma propriedade, um evento ou o tipo de retorno de um método como tendo um tipo anônimo. Da mesma forma, você não pode declarar um parâmetro formal de um método, propriedade, construtor ou indexador como tendo um tipo anônimo. Para passar um tipo anônimo, ou uma coleção que contém tipos anônimos, como um argumento para um método, você pode declarar o parâmetro como tipo object
. No entanto, o uso object
para tipos anônimos derrota o propósito da digitação forte. Se você precisar armazenar os resultados da consulta ou passá-los para fora do limite do método, considere usar uma struct ou classe nomeada comum em vez de um tipo anônimo.
Como os Equals métodos e GetHashCode em tipos anônimos são definidos em termos de e GetHashCode
Equals
métodos das propriedades, duas instâncias do mesmo tipo anônimo são iguais somente se todas as suas propriedades forem iguais.
Nota
O nível de acessibilidade de um tipo anônimo é internal
, portanto, dois tipos anônimos definidos em assemblies diferentes não são do mesmo tipo.
Portanto, instâncias de tipos anônimos não podem ser iguais entre si quando definidas em assemblies diferentes, mesmo quando têm todas as suas propriedades iguais.
Os tipos anônimos substituem o ToString método, concatenando o nome e ToString
a saída de cada propriedade cercada por chaves encaracoladas.
var v = new { Title = "Hello", Age = 24 };
Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"