Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

  1. Básico sobre Linq
  2. Ver as clásulas
  3. Selecionando dados
  4. Trabalhando com objetos
  5. Ordenando dados
  6. Agrupando dados
  7. Junção de coleções
  8. cláusula into
  9. cláusula let
  10. Métodos de extensão

Com a linguagem C#, podemos utilizar todos os recursos disponíveis no namespace .NET System.Linq, e realizar filtros em estruturas de dados dinâmicas ou coleções disponíveis em .Net.

As consultas criadas utilizando Linq são validadas em tempo de codificação sem que haja a necessidade de executá-las para detectarmos erros, o que torna seu uso vantajoso.

A Linq usa sua própria sintaxe que lembra as sintaxes utilizadas por bancos de dados como SQL Server, SQLite e outros.

Basicamente, utilizamos três cláusulas para a declaração e consultas ou queries(consultas) sobre coleções de dados:

  1. from in - Seleciona fonte de dados
  2. join- Faz união dados
  3. where - Filtra dados
  4. order by - Ordena dados
  5. group by - Agrupa dados
  6. select - Retorna objetos filtrados/agrupados/ordenados

Como resultado de uma query Linq, uma coleção do tipo interface IEnumerable<T> é retornada. Esse tipo de dado pertence ao namespace System.Collections.Generic já visto.

As queries criadas utilizando Linq podem retornar uma ou mais elementos de acordo com as necessidades e tipos de dados contidos na coleção.

A outras cláusulas existentes que serão vistas em futuros tópicos. Por enquanto, apenas as cláusulas acima serão abordadas para facilitar o estudo.

Com as cláusulas básicas vistas acima, podemos criar consultas simples para a obtenção de determinados elementos de uma coleção de dados em nossos programas.

Sintaxe
from objeto in colecao
where <condicao>
select objeto; 

No exemplo 1 abaixo, a query Linq apresentada irá realizar um filtro em que todos elementos pares serão retonardos da coleção array.

Exemplo 1
using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
	public static void Main()
	{
		int[] array = {0,1,2,3,4,5,6,7,8,9};
		
		IEnumerable<int>  x = from elemento in array
				              where elemento%2 == 0
				              select elemento;

		foreach( int el in x)
			Console.Write("{0} ",el);
	}
}
Saída
0 2 4 6 8

A cláusula where no exemplo acima, aceita condições mais complexas utilizando os operadores fornecidos pela linguagem C#.

A linguagem Linq também permite trabalhar com coleção de objetos. Na cláusula where podemos realizar filtros sobre os atributos de objetos de forma semelhante ao que foi feito com os elementos de um array.

Sintaxe
from objeto in colecao
where <condicao>
select  objeto; 

No exemplo 2 abaixo, a query Linq apresentada irá realizar um filtro em que todos elementos de um array de objetos retornando aqueles que possuam código 3 ou nome que iniciado por "Fu".

Exemplo 2
using System;
using System.Linq;
using System.Collections.Generic;

public class Objeto
{
	public int codigo;
	public string nome;
}

public class Program
{

	public static void Main()
	{
		Objeto[] array = { 
				 new Objeto(){ codigo = 1, nome = "Fulano"},
				 new Objeto(){ codigo = 2, nome = "Ciclano"},
				 new Objeto(){ codigo = 3, nome = "Beltrano"},
			              };
		
		IEnumerable<Objeto>  retorno = from elemento in array
						               where elemento.codigo == 3 || elemento.nome.StartsWith("Fu")
						               select elemento;
		
		foreach( var e in retorno)
			Console.Write("codigo:{0} nome:{1}",e.codigo,e.nome);
	}
}
Saída
codigo:1  nome:Fulano
codigo:3  nome:Beltrano

Nos exemplos anteriores, retornamos objetos de um mesmo tipo de dado que esta contido em uma coleção. Porém, podemos utilizar a cláusula select para retornar objetos de outros tipos utilizando o comando new.

Sintaxe
select new nome_classe() { atributo1 = valor1, atributoN = valorN };

No exemplo 3 abaixo, a query Linq apresentada irá realizar um filtro em todos elementos de um array de objetos retornando uma nova coleção de objetos da classe Objeto2 contendo os códigos dos elementos do array.

Exemplo 3
using System;
using System.Linq;
using System.Collections.Generic;

public class Objeto
{
	public int codigo;
	public string nome;
}

public class Objeto2
{
	public int id;
}

public class Program
{

	public static void Main()
	{
		Objeto[] array = { 
				new Objeto(){ codigo = 1, nome = "Fulano"},
				new Objeto(){ codigo = 2, nome = "Ciclano"},
				new Objeto(){ codigo = 3, nome = "Beltrano"},
				 };
		var  retorno = from elemento in array
			           select new Objeto2 { id = elemento.codigo};

		foreach( Objeto2 obj2 in retorno)
		{
			Console.WriteLine(obj2.id);
		}
	}
}
Saída
1
2
3

Com Linq também podemos ordenar uma coleção de dados. Para isso, precisamos adicionar a cláusula orderby, semelhante a SQL, em nossas consultas.

Sintaxe
orderby [campo] ordem
Onde
campo: Nome do campo ou atributo para ordenação. Opcional
ordem: ascending  - Ascendente
       descending - Descendente

No exemplo 4 abaixo, a query Linq apresentada irá realizar um filtro em que todos elementos de um array de objetos retornando aplicando uma ordenação descendente baseado no atributo codigo.

Exemplo 4
using System;
using System.Linq;
using System.Collections.Generic;

public class Objeto
{
	public int codigo;
	public string nome;
}
public class Program
{
	public static void Main()
	{
		Objeto[] array = { 
				new Objeto(){ codigo = 1, nome = "Fulano"},
				new Objeto(){ codigo = 2, nome = "Ciclano"},
				new Objeto(){ codigo = 3, nome = "Beltrano"},
			 };
		
		IEnumerable<Objeto>  retorno = from elemento in array
						               orderby elemento.codigo descending
						               select elemento;
		
		foreach( var e in retorno)
			Console.WriteLine("codigo:{0}  nome:{1}",e.codigo,e.nome);
	}
}
Saída
codigo:3  nome:Beltrano
codigo:2  nome:Ciclano
codigo:1  nome:Fulano

Com Linq também podemos agrupar uma coleção de dados. Para isso, precisamos adicionar a cláusula grouby em nossas consultas.

Sintaxe
group [objeto] by campo
Retorno
Uma coleção do tipo IEnumerable<IGrouping<T1, T2>>

T1: tipo de dado do grupo
T2: tipo de dado dos elementos

Cada agrupamento possui a propriedade Key que contém o grupo, de acordo com seu tipo de dado definido na cláusula group, e também cada elemento contido no grupo.

No exemplo 5 abaixo, a query Linq apresentada irá realizar um filtro em todos elementos de um array de objetos agrupando-os com base no atributo codigo.

Exemplo 5
using System;
using System.Linq;
using System.Collections.Generic;

public class Objeto
{
	public int codigo;
	public string nome;
}
public class Program
{
	public static void Main()
	{
		Objeto[] array = { 
				            new Objeto(){ codigo = 1, nome = "Fulano"},
				            new Objeto(){ codigo = 2, nome = "Ciclano"},
				            new Objeto(){ codigo = 2, nome = "Beltrano"},
			           };
        //agrupamento
        //IEnumerable<IGrouping<T1, T2>>
		var  retorno = from elemento in array
			           group elemento by elemento.codigo;
		
		foreach( var grupo in retorno) 
		{
			Console.WriteLine("grupo:{0}",grupo.Key); //campo de agrupamento
			foreach( var g in grupo)
			{          
				Console.WriteLine("\tcodigo:{0} nome:{1}",g.codigo,g.nome);
			}
		}
	}
}
Saída
grupo:1
    codigo:1 nome:Fulano
grupo:2
    codigo:2 nome:Ciclano
    codigo:2 nome:Beltrano

Com a cláusula join para realiza a junção entre coleções, com base em valores em comum, e assim retornar uma nova coleção de elementos criados a partir dos campos dessas coleções.

Sintaxe
join [objeto1] on objeto1.nome_campo equals objeto2.nome_campo
Onde
objeto1 e objeto2: objetos que contém campos para realiar o join

No exemplo abaixo, a query Linq apresentada irá realizar um join em todos elementos dos arrays alunos e salas utilizando os campos codSala para assim criar uma lista de aluno por sala.

Exemplo 6
using System;
using System.Linq;

public class Objeto
{
	public int codSala;
	public string nome;
}

public class Program
{

	public static void Main()
	{
		Objeto[] alunos = { 
				 new Objeto(){ codSala = 1, nome = "Fulano"},
				 new Objeto(){ codSala = 2, nome = "Ciclano"}, //mesma sala
				 new Objeto(){ codSala = 2, nome = "Beltrano"},//mesma sala
			              };
		
		Objeto[] salas = { 
				 new Objeto(){ codSala = 1, nome = "Sala 1"},
				 new Objeto(){ codSala = 2, nome = "Sala 2"},
				 new Objeto(){ codSala = 3, nome = "Sala 3"},
			              };
		
		var alunoSala = 
			from aluno in alunos
			join sala in salas on aluno.codSala equals sala.codSala
			select new { sala = sala.nome, aluno = aluno.nome };
			
		foreach( var e in alunoSala)
			Console.WriteLine("Sala: {0}   Aluno: {1}",e.sala,e.aluno);
	}
}
Saída
Sala: Sala 1   Aluno: Fulano
Sala: Sala 2   Aluno: Ciclano
Sala: Sala 2   Aluno: Beltrano

O namespace System.Linq possui vários métodos estáticos de extensão que possam ser utilizados para filtrar dados de coleções como First, Last , Sum entre outros. Nesta parte do tutorial vamos estudar esses métodos de extensão com exemplos.

Sintaxe
objeto_colecao.nome_metodo( expressao_lambda )
Onde
objeto_colecao: coleção de dados para filtrar
nome_metodo: nome do método de extensão
expressao_lambda: expressão lambda para filtrar dados da colecão
Exemplo
objeto_colecao.nome_metodo( x => x == 0 )

A chamada dos métodos de extensão podem ser aninhadas:

Exemplo
objeto_colecao.nome_metodo( x => x == 0 ).nome_metodo( x.atributo ); 
Tab. 1: Métodos
Método Descrição
Aggregate - Visitar
All Verifica se todas elementos satisfazem uma condição Visitar
Any Verifica se alguns elementos satisfazem uma condição Visitar
Append - Visitar
AsEnumerable - Visitar
Average Retonar a média de valores Visitar
Cast - Visitar
Chunk - Visitar
Concate Concatena uma coleção Visitar
Contains Verifica se coleção contém elemento Visitar
Count Retorna número de elementos Visitar
DefaultIfEmpty - Visitar
Distinct Faz distinção de elementos Visitar
DistinctBy O mesmo que Distinct, mas basedo em campo Visitar
ElementAt Retorna elemento de um posição Visitar
ElementAtOrDefault - Visitar
Empty Verifica se coleção está vazia Visitar
Except - Visitar
ExceptBy - Visitar
First Retorna primeiro elemento Visitar
FirstOrDefault Retorna primeiro elemento ou null Visitar
GroupBy Agrupa elementos Visitar
GroupJoin Faz união de grupos Visitar
Intersect - Visitar
Join Faz união de coleções Visitar
Last Retorna último elemento Visitar
LastOrDefault Retorna último elemento ou null Visitar
LongCount - Visitar
Max Retorna maior valor Visitar
MaxBy - Visitar
Min Retorna menor valor Visitar
MinBy - Visitar
OfType - Visitar
Order Ordena coleção. Ascendente Visitar
OrderBy Ordenação coleção por campo. Ascendente Visitar
OrderByDescending Ordena coleção de forma descendente por campo Visitar
Prepend - Visitar
Range - Visitar
Repeat - Visitar
Select Selectiona elementos Visitar
SelectMany Seleciona lista Visitar
SequenceEqual Compara coleções Visitar
Single - Visitar
SingleOrDefault - Visitar
Skip Pula N elementos em um resultado Visitar
SkipLast - Visitar
SkipeWhile - Visitar
Sum Retorna soma de valores Visitar
Take Retorna N elementos em um resultado Visitar
TakeLast - Visitar
TakeWhile - Visitar
ThenBy Agrupa campos para ordenação ascendente Visitar
ThenByDescending Agrupa campos para ordenação descendente Visitar
ToArray Converte em Array Visitar
ToDictionary Converte em Dictionary Visitar
ToHashSet - Visitar
ToList Converte em List Visitar
ToLookUp - Visitar
TryGetNonEnumeratedCount - Visitar
Union - Visitar
UnionBy - Visitar
Where Filtra elementos de uma coleção Visitar
Zip - Visitar
  1. 13/08/2025 - revisão 2 - Ajustes: pontuais, sintaxes e 'Objetivos'; Adição de 'junção'
  2. 10/10/2024 - revisão 1 - Adição: Explicação de Exemplos; Correção: Sintaxes; Ajustes pontuais
  3. 18/03/2024 - versão inicial