Desenvolvimento - C#

Uso de Array no C# - parte 2

Além de toda potencialidade que os arrays possibilitam dentro do C#, conforme vimos no artigo anterior, maior poder foi delegado aos programadores quando falamos de collections e nos aprofundamos nas classes que o framework nos traz para tratamento de arrays.

por Claudenir Andrade



Além de toda potencialidade que os arrays possibilitam dentro do C#, conforme vimos no artigo anterior, maior poder foi delegado aos programadores quando falamos de collections e nos aprofundamos nas classes que o framework nos traz para tratamento de arrays. Tenho a certeza que o estudo que fazermos agora sobre a classe System.Array e o System.Collections o deixará surpreso com a potencialidade que .NET FrameWork nos colocou a disposição para o tratamento de arrays e as várias maneiras e possibilidades de trabalho.

Visão Geral Sobre a Classe System.Array

Interessante notar que os tipos int, char, double etc. são chamados de "type Values" ou tipos de valores, o que significa isso? Significa que uma variável do Tipo INT contem um valor inteiro mas o objeto INT ou a palavra reservada que você utilizou para declarar a variável do tipo inteira é um Tipo de Valor, o Valor contido é um inteiro, ou seja, sua variável int contador; por exemplo, é uma variável do tipo inteiro de um valor inteiro, por isso é classificado como um "type value" ou um tipo valor, que em nosso exemplo é um tipo que contém um valor inteiro. No caso das arrays, o tratamento e diferente, porque? Porque as arrays não são tipo de valores e sim referência a Tipos de Valores, ou seja, quando eu tenho um array de inteiros de 10 posições é porque nossa array é uma array que faz referência a 10 tipo de inteiros que possuem valores inteiros, hierarquicamente poderíamos definir da seguinte forma:

int[] inteiros = new int[10]; -> Um Array de inteiros que que faz referência a 10 Tipos de Valores ("Type Values") Inteiros, que contém Valores inteiros.

Este conceito é interessante porque é através deles que você começa a entender porque determinados métodos um array e inteiro possui e um Inteiro não possui. Também fica bem fixo em nosso conhecimento que é existe uma diferença entre CONTER um valor, SER um tipo de valor e fazer REFERÊNCIA a um tipo de valor, como é o caso dos arrays.

Agora, transportando isso para nossa classe Array, começamos a entender que sua inicialização e uso diferem quando estamos utilizando nossa Classe System.Array. Porque? Porque nossa classe herda um nível a mais dos que comentamos anteriormente (Conter, Ser, referência) na verdade nossa classe herda todos os tipos de arrays possível, double[];object[];int[]... o que possibilita uma manutenção muito mais simples de nosso array.

Prova disso é o exemplo abaixo:

Array aInteiros = new int[10]; //OK
int[] aiInteiros= new int[10]; //OK

Neste caso a inicialização funciona Normalmente e OK, poderem se inicializarmos nossa aiInteiros (que deriva da classe array) da mesma maneia como inicializamos nossa array aInteiros então teremos um problema de compilação, porque? Veja o exemplo abaixo:

//Erro de compilação
Array aInteiros = {1,2,3,4,5,6,7,8,9,0};
int [] aiInteiros = {1,2,3,4,5,6,7,8,9,0}; 
//ok, inicialização Correta
Array aInteiros = new int[10]{1,2,3,4,5,6,7,8,9,0};
int [] aiInteiros = {1,2,3,4,5,6,7,8,9,0};

Isso porque sempre quando utilizamos a classe array, devemos indicar a que tipo esta classe esta fazendo referência.

Conhecendo o "Collection Classes"

O NameSpace cedido pelo .Net FrameWork System.Collections é sem duvida um mundo novo para os amantes de programação Windows e nos dá possibilidades incríveis de trabalharmos com arrays (neste caso como Objetos Efetivamente, pois podem conter QUALQUER VALOR) e termos toda flexibilidade necessária para realizarmos nossas tarefas.

Existem quatro poderosos objetos que o Collections nos disponibiliza, são eles: QUEUE, STACK, SORTED LIST e ARRAY LIST.

1) QUEUE

Este é sem dúvida um dos mais poderosos "contrutores" de arrays, por assim dizer, possibilita a concatenação de strings e obedece a cadeia conhecida como FIFO (First Intput, First OutPut - primeiros que entra, primeiro que sai) nada muito diferente do que já conhecemos hoje, porém com algumas vantagens. Na figura abaixo você pode observar os diversos métodos que estão a disposição quando utilizado o QUEUE para a definição de sua variável.

Queue

Figura 1: Método mais utilizado o Enqueue que permite a concatenação nas posições subseqüentes de nossa array, acima está o Dequeue que possibilita a retirada de valores de nossa array obedecendo a ordem FIFO.

É muito fácil trabalhar com o tipo QUEUE, por exemplo, vamos montar um array com QUEUE onde nosso objetivo é concatenar nomes dos 5(cinco) primeiros ganhadores de uma competição e depois imprimi-los.

Verifique antes, em seu projeto em C#, se esta declarado os seguintes NameSpaces em seu código:

using System;
using System.Collections;

Uma vez certificado disso adicione o seguinte código:

Queue qInteiros = new Queue();
qInteiros.Enqueue("Ganhador 1");
qInteiros.Enqueue("Ganhador 2");
qInteiros.Enqueue("Ganhador 3");
qInteiros.Enqueue("Ganhador 4");
qInteiros.Enqueue("Ganhador 5");

while( qInteiros.Count!=0)
	Console.WriteLine(qInteiros.Dequeue().ToString());

Para ver o resultado pressione ALT+CTRL+O (letra O) para mostrar para você a janela de OUTPUT.

Observe então as facilidades herdadas pelo Collection classes e pelo uso do Objeto QUEUE, são eles:

  1. Não foi necessário indicar o tamanho da variável, ou seja, ela se dimensiona de acordo com sua necessiadade;
  2. Não foi necessário um contador para indicar até quando nosso while deveria estar imprimindo o conteúdo de nossa array de strings, porque isso é totalmente controlado pelos processos herdados do QUEUE desde a classe Collections.

Porém aqui vale um aviso, o DEQUEUE, remove literalmente os dados de nossa array, não permitindo uma nova impressão do conteúdo de nosso array, para que você possa extrair os dados de um QUEUE, você poderá utilizar o método PEEK(), que extrai o conteúdo de nosso array sem removê-lo literalmente de nossa variável.

Aí, uma vez descoberto o Collection Classes você sem duvida poderá passear pelos métodos oferecidos por ele e descobrir que sem nenhum esforço, por exemplo, você pode fazer uma consulta a seu array e descobrir que determinada string está contida e nosso array, utilizando apenas o método CONTAINS, por exemplo:

qInteiros.Contains("Ganhador 5"); 	//Devolverá TRUE
qInteiros.Contains("CSHARP"); 	//Devolverá FALSE
qInteiros.Contains("ganhador 5"); 	//Devolverá FALSE-ele É "sensitive case"

Aqui também vale outro aviso, que para você ler um valor especifico de uma posição de um QUEUE é necessário copiá-lo inteiramente para um array e logo acessar ao índice especifico deste array ao que você copiou os valores do QUEUE, para partes de seu código em que você necessitara acessar a um valor específico de um índice de seu array, não aconselhamos o uso do QUEUE, onde é super pratico para "filas", por assim dizer, para estes casos aconselhamos o uso do ArrayList que abordaremos alguns parágrafos a frente.

Mas de todas as formas segue a maneira de como copiar e acessar a um valor especifico do QUEUE, sem perder o conteúdo de sua variável (por não utilizar o DEQUEUE):

System.String[] MyArray = new System.String[10];
Queue qInteiros = new Queue();

qInteiros.Enqueue("Ganhardor 1");
qInteiros.Enqueue("Ganhardor 2");
qInteiros.Enqueue("Ganhardor 3");
qInteiros.Enqueue("Ganhardor 4");
qInteiros.Enqueue("Ganhardor 5");

qInteiros.CopyTo(MyArray,0);
Console.WriteLine("Index 3 =" + MyArray[3].ToString());

2) STACK

O STACK possui os mesmos métodos do QUEUE porém ele ao invés de utilizar o ENQUEUE, utiliza o Push, isso mesmo como no ASM, lembra??!! E ao invés de utilizar o DEQUEUE, utiliza o POP. Fácil!! E ao invés de utilizar-se do método FIFO - como no QUEUE - utiliza-se do método de enfileiração LIFO (Last Input First OutPut - Ultimo que entra, primeiro que sai).Nada com um bom trecho de código para nos ajudar a entender isso.

Não esqueça de certificar-se do uso do NameSpace System.Collections, e uam vez certificado adicione a seguinte linha de código a um Botão, por exemplo:

Stack scArray = new Stack();

scArray.Push("Ganhador 1");
scArray.Push("Ganhador 2");
scArray.Push("Ganhador 3");
scArray.Push("Ganhador 4");
scArray.Push("Ganhador 5");
			
while(scArray.Count!=0)
	Console.WriteLine(scArray.Pop().ToString());
Stack

Figura 2: Resultado do uso do STACK, observe que foi aplicado o LIFO como ordem de impressão e captura dos dados (Last Input, First OutPut)

3) Sorted List

O "Sorted List", conforme o próprio nome diz, serve para trabalharmos com listas ordenadas dentro de nosso array, mas nos permite mais que isso, permite também que você possa acessar ao conteúdo através de um Label e não mais através de um Índice, o que pode em alguns momentos de nossa codificação ser muito, muito interessante. Para este Objeto herdado de nosa Classe System.Collections, existem dois métodos importantes que vamos estudar agora, e que são a chave para o bom uso do Tipo SortedList de nossa classe Collections.

KEY e Value - Que conforme os próprios nomes me ingles indicam, são as chaves que nos servirão para buscas dentro de nosso array e os valores dentro de nosso array.

Nada melhor do que verificarmos o funcionamento disso na pratica, vamos lá:

SortedList Paises = new SortedList();

//Preenchendo nossa lista, voce adicina a chave de busca e o valor 
//que você deseja estar armazenando em nossa Array
			
Paises.Add("Brasil",0);
Paises.Add("Espanha",1);
Paises.Add("Alemanha",2);
Paises.Add("Mexico",3);
Paises.Add("Italia",4);
			
foreach( DictionaryEntry locais in Paises )
Console.WriteLine(locais.Key.ToString() + "=" + locais.Value.ToString());
SortedList

Figura 3: Observe que a lista foi impressa, agora não com o FIFO ou LIFO e sim de forma ordenada através da propriedade KEY de nossa Lista

Viram? Sem dúvida o sorted list pode ser uma verdadeira mão na roda para alguns processos que necessitemos controlar.

//Este código remove a Alemanha de nossa lista e o ForEach imprimirá apenas 
//os outros paises, redimensionando sem necessidade de código, nossa array.
Paises.Remove("Alemanha");
foreach( DictionaryEntry locais in Paises )
Console.WriteLine(locais.Key.ToString() + "=" + locais.Value.ToString());

No código abaixo, o resultado será ESPANHA, porque estamos lidando com um SortedList, ou seja, independente de como estamos inputando os dados, o FrameWork sempre tratará este dado já como ordenado e não irá considerar a ordem de como foram colocados em nosso array.

Veja o Código Abaixo:

SortedList Paises = new SortedList();
		
Paises.Add("Brasil",0);
Paises.Add("Espanha",1);
Paises.Add("Alemanha",2);
Paises.Add("Mexico",3);
Paises.Add("Italia",4);

foreach( DictionaryEntry locais in Paises )
Console.WriteLine(locais.Key.ToString() + "=" + locais.Value.ToString());

			
Console.WriteLine(Paises.GetKey(2).ToString());
SortedList e DictinaryEntry

Figura 4: Resultado do Código acima -> É impresso o Key Espanha porque ela é quem contem o índice numero 2(dois) já com a lista ordenada. [0]=Alemanha, [1]=Brasil, [2]=Espanha.

4) ArrayList

Este é outro membro do Collection Class que permite um trabalho flexível com os Arrays. Uma das características do ArrayList é a possibilidade de redimensionar-se de acordo com a necessidade, sem que tenhamos que indicar previamente seu tamanho, a possibilidade de trabalharmos com o Valor de nosso Array e com o Índice de nosso Array também é muito interessante e economiza sem duvida muito trabalho no momento em que desejamos, por exemplo, remover um valor de nosso array.

Por exemplo, veja o código abaixo:

ArrayList Extenso = new ArrayList();

Extenso.Add("UM");
Extenso.Add("DOIS");
Extenso.Add("TRES");
Extenso.Add("QUATRO");
Extenso.Add("CINCO");
Extenso.Add("SEIS");

for(int contador=0; contador!=Extenso.Count; contador++)
	Console.WriteLine(Extenso[contador].ToString());
			
Extenso.Remove("CINCO");//Removemos o Índice que contem o valoro "CINCO"
Extenso.RemoveAt(2); //Removemos o Índice 2, independente de seu valor

for(int contador=0; contador!=Extenso.Count; contador++)
	Console.WriteLine(Extenso[contador].ToString());

O Resultado do primeiro FOR será:

UM
DOIS
TRES
QUATRO
CINCO
SEIS

O Resultado do Segundo FOR será:

UM
DOIS
QUATRO
SEIS

Bem, é isso aí!!! Espero que vocês tenham gostado do resultado de nosso estudo do collection classes e toda a potencialidade oferecida por este classe, que sem duvida facilitará em muito nosso dia-a-dia.

No próximo artigo vamos estudar outra particularidade interessante do C#.

Um Abraço!!

Claudenir Campos Andrade é MVP - Microsoft, Autor do livro "Automação Comercial com VB.net e C#" (www.erica.com.br) , gerencia a equipe de desenvolvimento de sw da Bematech e o programa Bematech Software Partners. Escreve artigos para o site MSDN, revista desenvolvedores, palestrantes de diversos eventos de Automação comercial e o uso da plataforma .net neste mercado como o Tecnical Day da Linha de Código e do Fórum de Desenvolvimento promovido pela Fórum Access, Seminários na Microsoft e evento exclusivos dirigidos ao publico de desenvolvedores para automação comercial. (claudenir_campos@hotmail.com - claudenir@bematech.com.br)

Claudenir Andrade

Claudenir Andrade - Formado pela Academia de Sistemas Informáticos de Madrid, trabalha com automação comercial há nove anos, foi responsável pela Homologação e aprovação de ECFs brasileiros em países como Equador e Venezuela, gerencia a equipe de desenvolvimento da Daruma Automação. Autor do primeiro livro de automação comercial no Brasil - "Automação Comercial com VB.Net e C#", é também MVP da Microsoft e está criando e definindo o Modelo XML para Automação Comercial, escreve artigos também para o site MSDN e pode ser contatado pelo e-mail - claudenir@daruma.com.br