C#  - Apresentando Enumerable.Range


 Hoje vamos apresentar o recurso Enumerable.Range da linguagem C#.

O método Enumerable.Range gera uma sequência de números dentro de um intervalo especificado. Para isso ele usa o método estático Range() da classe Enumerable que esta no namespace System.Linq.

Sintaxe:

Enumerable.Range (int start, int count);

O retorno  é um IEnumerable<int> que contém a sequência gerada. Lembre-se de que cada número subsequente é incrementado em 1, o que também significa que os elementos estão em ordem crescente. No entanto, isso pode ser alterado com alguns truques do Linq (veremos isso mais adiante).

O método Range funciona apenas com números inteiros, podemos fazê-lo funcionar também com floats.

Exemplos básico

Vamos começar com um exemplo bem básico: imprimir 50 números a partir do número 5 :

Resultado:

Gerando uma sequência na ordem reversa e descendente

Aqui você sente a simplicidade do Linq para fazer a reversão de uma sequência. Basta usar o método Reverse.

Confira o exemplo a seguir, que imprime os números de 10 a 1:

Resultado:

Gerando uma sequência de números pares/ímpares

Aqui para gerar o número de elementos esperados, definimos a quantidade, e usando o método Select, e aplicamos o critério desejado :

 var pares = Enumerable.Range(0, 10).Select(n => n * 2);

Ou podemos gerar um certo número de elementos e a seguir selecionamos apenas os que correspondem ao critério (pares ou ímpares) usando a cláusula Where:

var pares = Enumerable.Range(1, 20).Where(numero => numero % 2 == 0);

ou

var ímpares = Enumerable.Range(1, 20).Where(numero => numero % 2 == 1);

Resultados:

1- Gerando 10 números pares (Select)

2- Gerando 20 números e extraindo os números ímpares (Where)

Trabalhando com decimais

O recurso Enumerable.Range não funciona com floats apenas com inteiros.

Podemos contornar essa limitação usando um artifício.

No exemplo a seguir vamos gerar uma sequência de números de 1 até 2 com incremento de 0.1:

 var numeros = Enumerable.Range(10, 10).Select(numero => numero / 10f);

Aqui para cada número da sequência estamos dividindo por 10:

resultado:

Trabalhando com strings

Mas o melhor do método Range() é que você não precisa usá-lo apenas para produzir números, você pode usar a sequência que ele gera diretamente ou como ponto de partida para gerar uma expressão LINQ mais complexa.

Por exemplo, se quisermos gerar uma série de strings para tamanhos de fonte que desejamos usar podemos fazer isso facilmente:

var fontes = Enumerable.Range(1, 10).Select(i => (i * 10) + "pt").ToArray();

resultado:

Usando Range para gerar múltiplos objetos complexos

Outro uso do método Range() que ele pode ser útil é repetir alguma ação várias vezes.

Por exemplo, digamos que queremos criar e iniciar várias instâncias de uma Task (tarefa) para realizar algum trabalho em paralelo.

Poderíamos fazer isso usando uma alocação de um array padrão e a seguir uma laço loop for:

var NumeroTarefas = 10;

// constroi o array de um tamanho adequado
Task[] tasks = new Task[NumeroTarefas];

// percorre cada index e cria uma nova instância
for (int i = 0; i < NumeroTarefas; i++)
{ 
        tasks[i] = TaskFactory.StartNew("código");
}

Agora aplicando o método Range, resumimos o código acima em uma única expressão LINQ:

var NumeroTarefas = 10; 
Task[] tasks = Enumerable.Range(1, NumeroTarefas)
                       .Select(i => TaskFactory.StartNew("código"))
                      .ToArray();

Dessa forma o método Enumerable.Range() executa uma função muito simples, mas seus resultados podem ser usados para conduzir expressões LINQ muito mais complexas.

Sinta-se à vontade para usá-lo para gerar sequências inteiras simples e até sequências de uma ação repetida.

De qualquer forma, é um recurso que você deve conhecer.

Pegue o código do projeto aqui:  CShp_Enumerable1.zip

Referências:


José Carlos Macoratti