LINQ - Visão geral - Inicializadores de objetos e coleções


E cá estou novamente a falar sobre LINQ dessa vez para dar um visão geral revendo e detalhando conceitos importantes sobre LINQ que se bem entendidos poderão nos ajudar muito nas tarefas do dia a dia.

O foco do artigo de hoje serão os tipos anônimos que permitem a criação de objetos sem escrever um definição de classe para o tipo de dados. Em vez disso, o compilador gera uma classe para você. A classe não possui um nome utilizável, herda diretamente da Object e contém as propriedades que você especificar ao declarar o objeto.

Porque não foi especificado o nome do tipo de dados, ele é conhecido como um tipo anônimo.

Recordando um pouco sobre o LINQ

A LINQ - Language Integrated Query é um novo recurso da plataforma .NET, que estende as capacidades de consulta, usando C # e Visual Basic. Ela esta disponível tanto no Visual Studio como nas versões Express e vem com assemblies de provedor de LINQ que permitem o seu uso com diferentes fontes de dados como coleções de memória, banco de dados relacionais , Datasets, documentos XML e outras fontes de dados.

Tanto no Visual Studio como nas versões Express as linguagens Visual C # e Visual Basic implementam as extensões da linguagem LINQ; essas extensões da linguagem LINQ usam a nova API Standard Query Operators, que é a linguagem de consulta para qualquer coleção que implementa a interface IEnumerable<T>.

Isso significa que todas as coleções e arrays podem ser consultadas usando LINQ. As classes de coleções precisam apenas implementar a interface IEnumerable<T>, para habilitá-lo a usar a LINQ para consultar as coleções.

A Standard Query Operador (Operadores de consulta padrão) é uma API que permite a consulta de qualquer array. ou coleção .NET. Essa API consiste em os métodos declarados na classe estática System.Query.Sequence localizada no assembly System.Query.dll.

A figura abaixo mostra a arquitetura da LINQ que pode consultar diferentes tipos de dados usando diferentes linguagens:

LINQ to Objects Usado para acessar estruturas de dados na memória. Consulta qualquer tipo que suporta IEnumerable (Of T) (Visual Basic) ou IEnumerable<T> (C #).
LINQ to SQL Usado para gerenciar os dados relacionais como objetos. É parte da família de tecnologias ADO.NET. Traduz a consultas LINQ no modelo de objeto para SQL e as envia ao banco de dados para execução. Quando o banco de dados retorna o resultado, A LINQ to SQL os traduz de volta para os objetos com o qual podemos trabalhar. A LINQ para SQL também suporta os procedimentos armazenados e funções definidas pelo usuário no banco de dados.
LINQ to DataSets Facilita a consulta dos dados armazenados em cache em DataSet.Um DataSet é um conjunto de dados desconectado e consolidado a partir de fontes de dados diferentes.
LINQ to Entities O Entity Data Model é um modelo conceitual de dados que podem ser usado para modelar os dados de forma que as aplicações podem interagir com dados como entidades ou objetos. Através do Modelo de Dados Entidade, ADO.NET expõe as entidades como objetos.
LINQ to XML Fornece as capacidades para modificação de documento em memória do DOM - Document Object Model e suporta consultas LINQ. Com LINQ to XML você pode consultar, modificar, navegar e salvar as alterações de um documento XML. Ele permite escrever consultas para navegar e recuperar uma coleção de documentos e atributos sendo semelhante ao XPath e XQuery.

Dentre os recursos que foram implementado para dar suporte ao LINQ os tipos anônimos cumprem um papel importante.

Inicializadores de Objetos (Object Initializers)

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 de tipos anônimo e também permitem atribuir valores para as propriedades de um objeto no momento da criação do objeto.

Normalmente nas versões anteriores da plataforma .NET (.NET 1.1 e 2.0), definimos a classe com propriedades, em seguida criamos a instância, e então definimos os valores das propriedades quer no construtor ou na função que está usando o objeto.

A partir da versão 3.0 podemos definir os valores no momento da própria criação. Considere o seguinte exemplo de classe Produto com duas propriedades auto-implementadas. (Propriedades auto-implementadas são as propriedades sem uma variável local para armazenar o valor da propriedade.)

namespace Macoratti
{
    class Produto
    {
        public string Nome { get; set; }
        public double Preco { get; set; }
    }
}

Agora quando criamos um novo objeto do tipo Produto podemos atribuir valores diretamente ao mesmo:

using Macoratti;

namespace InicialodoresObjetos
{
    class Program
    {
        static void Main(string[] args)
        {
            Produto produto1 = new Produto { Nome = "Teclado sem fio Microsoft", Preco = 51.25 };
        }
    }
}

Antes você tinha que criar uma instância do objeto e atribuir os valores.

Usando este recurso podemos também atribuir um valor a qualquer campo acessível da classe e não necessariamente somente para as propriedades implementadas. No exemplo a seguir temos um campo chamado descricao adicionado a classe Produto:

namespace Macoratti
{
    class Produto
    {
        public string Nome { get; set; }
        public double Preco { get; set; }
        public string descricao;
    }
}

Agora eu posso atribuir valores a este novo campo adicionado à classe na hora de criar o próprio objeto.

As expressões de consulta LINQ fazem uso desses inicializadores de objeto para inicializar tipos anônimos. (Em meu artigo sobre Tipos anônimos, temos uma consulta seleção que cria um tipo anônimo com propriedades. Os valores também são atribuídos utilizando inicializadores de objeto.)

Os inicializadores de coleção use inicializadores de objeto para inicializar a sua coleção de objetos. Usando um inicializador de coleção, não temos para inicializar objetos fazendo várias chamadas. No meu artigo sobre Tipos anônimos, nós criamos uma lista chamada pizzaLista é uma coleção de objetos Pizza .

Todos os objetos Pizza adicionados à coleção são inicializados usando o inicializador de coleção, como segue:

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

namespace Macoratti
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Pizza> pizzaLista = new List<Pizza>
            {
                new Pizza
                {
                    nome="Mussarela",
                    ingredientes=" mussarela , farinha, leite, ovos, tomate",
                    gordura="20g",
                    colesterol="50mg",
                    carbohidratos="35g",
                    proteina="4g",
                    preco=28.50
                },
                new Pizza
                {
                    nome="Calabreza",
                    ingredientes="farinha, leite, ovos, tomate, calabreza",
                    gordura="16g",
                    colesterol="65mg",
                    carbohidratos="26g",
                    proteina="4g", 
                    preco=31.80
                };

            var PizzaMaisBarata = from pizza in pizzaLista
                                              where pizza.preco < 35
                                              select new
                                              {
                                                    Nome = pizza.nome,
                                                    Preco = pizza.preco
                                              };

            Console.WriteLine("Pizzas com preco inferior a 35 reais :");
            foreach (var pizza in PizzaMaisBarata)
            {
                Console.WriteLine("{0} é {1}", pizza.Preco, pizza.Nome);
            }
            Console.ReadKey();
        }
    }
}
C#

Os inicializadores de objetos e os construtores são diferentes

Os inicializadores de objetos são usados para definirmos valores para as propriedades públicas no momento da criação do objeto.

Um construtor é um método definido em um tipo que tem um determinado número de parâmetros e é usada para criar e inicializar um objeto.

Um inicializador de objeto é o código que é executado em um objeto depois de um construtor e pode ser usado para definir de forma sucinta o número de campos sobre o objeto com os valores especificados.

A utilização de um inicializador requer o uso explícito ou implícito de um construtor para criar o objeto inicial.

Eu sei é apenas LINQ mas eu gosto...

"Meus filhinhos , estas coisas vos escrevo, para que não pequeis; e se alguém pecar, temos um advogado para com o Pai, Jesus Cristo, o justo." I João 2:1

Referências:


José Carlos Macoratti