Compartilhar via


funcionalidades do C# que dão suporte a LINQ

Expressões de consulta

As expressões de consulta usam uma sintaxe declarativa semelhante a SQL ou XQuery para consultar coleções System.Collections.Generic.IEnumerable<T>. No tempo de compilação, a sintaxe de consulta é convertida em chamadas de método para a implementação de um provedor LINQ dos métodos de consulta padrão. Os aplicativos controlam os operadores de consulta padrão que estão no escopo, especificando o namespace apropriado com uma diretiva using. A expressão de consulta a seguir pega uma matriz de cadeias de caracteres, agrupa-os de acordo com o primeiro caractere da cadeia de caracteres e ordena os grupos.

var query = from str in stringArray
            group str by str[0] into stringGroup
            orderby stringGroup.Key
            select stringGroup;

Variáveis tipadas implicitamente (var)

Você pode usar o modificador var para instruir o compilador a inferir e atribuir o tipo, conforme mostrado aqui:

var number = 5;
var name = "Virginia";
var query = from str in stringArray
            where str[0] == 'm'
            select str;

Variáveis declaradas como var são fortemente tipadas, assim como variáveis cujo tipo você especifica explicitamente. O uso de var possibilita a criação de tipos anônimos, mas apenas para variáveis locais. Para obter mais informações, consulte Variáveis locais de tipo implícito.

Inicializadores de objeto e coleção

Os inicializadores de objeto e de coleção possibilitam a inicialização de objetos sem chamar explicitamente um construtor para o objeto. Os inicializadores normalmente são usados em expressões de consulta quando projetam os dados de origem em um novo tipo de dados. Supondo uma classe chamada Customer com propriedades públicas Name e Phone, o inicializador de objeto pode ser usado como no código a seguir:

var cust = new Customer { Name = "Mike", Phone = "555-1212" };

Continuando com sua classe Customer, suponha que haja uma fonte de dados chamada IncomingOrders, e que para cada pedido com um grande OrderSize, você gostaria de criar um novo Customer com base nessa ordem. Uma consulta LINQ pode ser executada nessa fonte de dados e usar a inicialização do objeto para preencher uma coleção:

var newLargeOrderCustomers = from o in IncomingOrders
                            where o.OrderSize > 5
                            select new Customer { Name = o.Name, Phone = o.Phone };

A fonte de dados pode ter mais propriedades definidas do que a classe Customer como OrderSize, mas com a inicialização do objeto, os dados retornados da consulta são moldados para o tipo de dados desejado; você escolhe os dados relevantes para sua classe. Como resultado, agora você tem um System.Collections.Generic.IEnumerable<T> cheio dos novos Customers que você queria. O exemplo anterior também pode ser escrito na sintaxe do método LINQ:

var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });

A partir do C# 12, você pode usar uma expressão de coleção para inicializar uma coleção.

Para saber mais, veja:

Tipos anônimos

O compilador constrói um tipo anônimo. O nome do tipo só está disponível para o compilador. Os tipos anônimos fornecem uma maneira conveniente de agrupar um conjunto de propriedades temporariamente em um resultado de consulta, sem a necessidade de definir um tipo nomeado separado. Os tipos anônimos são inicializados com uma nova expressão e um inicializador de objeto, como mostrado aqui:

select new {name = cust.Name, phone = cust.Phone};

A partir do C# 7, você pode usar tuplas para criar tipos sem nome.

Métodos de Extensão

Um método de extensão é um método estático que pode ser associado a um tipo, para que ele possa ser chamado como se fosse um método de instância no tipo. Esse recurso permite que você, na verdade, "adicione" novos métodos a tipos existentes sem realmente modificá-los. Os operadores de consulta padrão são um conjunto de métodos de extensão que fornecem a funcionalidade de consulta LINQ para qualquer tipo que implementa IEnumerable<T>.

Expressões lambda

Uma expressão lambda é uma função embutida que usa o operador => para separar os parâmetros de entrada do corpo da função e pode ser convertida em tempo de compilação em um representante ou em uma árvore de expressão. Na programação LINQ, você encontra as expressões lambda ao fazer chamadas de método diretas aos operadores de consulta padrão.

Expressões como dados

Os objetos de consulta são combináveis, o que significa que você pode retornar uma consulta de um método. Os objetos que representam consultas não armazenam a coleção resultante, mas sim as etapas para produzir os resultados quando necessário. A vantagem de retornar objetos de consulta de métodos é que eles podem ser ainda mais modificados e combinados. Portanto, qualquer valor retornado ou parâmetro out de um método que retorna uma consulta também deve ter o tipo. Se um método materializa uma consulta em um tipo List<T> ou Array concreto, ele retornará os resultados da consulta em vez da própria consulta. Uma variável de consulta retornada de um método ainda pode ser combinada ou modificada.

No exemplo a seguir, o primeiro método QueryMethod1 retorna uma consulta como um valor retornado e o segundo método QueryMethod2 retorna uma consulta como um parâmetro out (returnQ, no exemplo). Em ambos os casos, é uma consulta que é retornada, não os resultados da consulta.

IEnumerable<string> QueryMethod1(int[] ints) =>
    from i in ints
    where i > 4
    select i.ToString();

void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
    returnQ = from i in ints
              where i < 4
              select i.ToString();

int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

var myQuery1 = QueryMethod1(nums);

A consulta myQuery1 é executada no loop foreach a seguir.

foreach (var s in myQuery1)
{
    Console.WriteLine(s);
}

Coloque o ponteiro do mouse sobre myQuery1 para ver o tipo.

Execute também a consulta retornada de QueryMethod1 diretamente, sem usar myQuery1.

foreach (var s in QueryMethod1(nums))
{
    Console.WriteLine(s);
}

Coloque o ponteiro do mouse sobre a chamada a QueryMethod1 para ver o tipo de retorno.

QueryMethod2 retorna uma consulta como o valor do seu parâmetro out:

QueryMethod2(nums, out IEnumerable<string> myQuery2);

// Execute the returned query.
foreach (var s in myQuery2)
{
    Console.WriteLine(s);
}

Você pode modificar uma consulta usando a composição de consultas. Nesse caso, o objeto de consulta anterior é usado para criar um objeto de consulta. Esse novo objeto retorna resultados diferentes do objeto de consulta original.

myQuery1 = from item in myQuery1
           orderby item descending
           select item;

// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
    Console.WriteLine(s);
}