domingo, 3 de maio de 2009

C# - Passando arrays como parâmetro para métodos

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2009/05/03/C-Passando-arrays-como-parametro-para-metodos.aspx


Para passar um array como parâmetro a algum método, basta passá-lo sem os colchetes, como abaixo:

   1:  int[] array = new int[5];

   2:  teste.dobrarArray(array);

IMPORTANTE: O array é uma variável que "guarda" um objeto, mas não guarda o objeto em si. Ao invés disso, o array guarda uma referência a esse objeto (o local na memória onde esse objeto está).

No código acima, todos os elementos desse array são passados como parâmetro na linha 2. Por questões de performance, por default, o que é passado é apenas uma referência do array, ou seja, o espaço em memória onde o array está armazenado. Isso significa que as mudanças feitas a qualquer elemento desse array dentro do método implicarão em mudanças na variável do chamador desse método, pois o parâmetro foi passado por referência.

Resumindo: Por padrão, qualquer array ou objeto que é passado como parâmetro a um método, é passado por referência. Para saber mais sobre a diferença entre passar um valor, por valor ou referência: http://ericmilaneze.blogspot.com/2009/04/c-metodos-passando-parametros-por-valor.html

No caso de precisar passar um elemento de um array como parâmetro a um método, esse elemento (ex.: array[1]) é passado por valor ou por referência? Isso vai depender se foram usadas as palavras-chave ref ou out, ou nenhuma das duas. Se nenhuma foi usada, é passado por valor, caso contrário, por referência. Nesse caso, aplicam-se as mesmas regras no seguinte post: http://ericmilaneze.blogspot.com/2009/04/c-metodos-passando-parametros-por-valor.html

Apesar do array já ser uma variável que guarda uma referência e ser passado por padrão como referência a um método, existe uma diferença entre passar essa referência por referência ou por valor (utilizando a palavra-chave ref ou não). Quando se passa uma referência por referência, existe a possibilidade de recriar essa referência dentro do método, caso contrário não. O exemplo abaixo ilustra essa diferença.

Exemplo:

   1:  class ArrayReferenceTest

   2:  {

   3:      public void dobrarArray(int[] array)

   4:      {

   5:          for (int i = 0; i < array.Length; array[i] = i++ * 2) ;

   6:   

   7:          array = new int[3];

   8:      }

   9:   

  10:      public void dobrarArray(ref int[] array)

  11:      {

  12:   

  13:          for (int i = 0; i < array.Length; array[i] = i++ * 2) ;

  14:   

  15:          array = new int[3];

  16:      }

  17:  }


Utilizando o exemplo:

   1:  class Program

   2:  {

   3:      static void Main(string[] args)

   4:      {

   5:          ArrayReferenceTest teste = new ArrayReferenceTest();

   6:   

   7:          int[] array = new int[5];

   8:   

   9:          // populando o array

  10:          for (int i = 0; i < array.Length; array[i] = i++) ;

  11:   

  12:          foreach (int i in array)

  13:              Console.Write("." + i.ToString() + ".");

  14:   

  15:          Console.WriteLine("\n");

  16:   

  17:   

  18:          // executa o método que multiplica por 2 cada elemento

  19:          teste.dobrarArray(array);

  20:   

  21:          foreach (int i in array)

  22:              Console.Write("." + i.ToString() + ".");

  23:   

  24:   

  25:          Console.WriteLine("\n");

  26:   

  27:   

  28:          // executa o método que multiplica por 2 cada elemento

  29:          teste.dobrarArray(ref array);

  30:   

  31:          foreach (int i in array)

  32:              Console.Write("." + i.ToString() + ".");

  33:   

  34:          Console.ReadLine();

  35:      }

  36:  }

Na classe ArrayReferenceTest, nas linhas 7 e 15, o array é recriado. Na linha 7, o código não possui nenhum efeito, pois o array não foi passado por referência. Já na linha 15, o array é recriado e pode ser, inclusive, redimensionado. Após ser recriado, não existe nada que popule os elementos desse array, portanto eles passam a ter um valor int default: 0.

Nenhum comentário: