terça-feira, 25 de março de 2014

Diferença entre out e ref no C# (Blick)

Olhando um código num projeto, encontrei dois métodos que utilizam formas diferentes de passar um valor por referência. Em um deles encontrei o uso de "out" e no outro o uso de "ref".
Quando estamos desenvolvendo um método e precisamos retornar dois ou mais valores, precisamos utilizar a passagem de valor por referência, daí o nosso método altera o valor que foi passado e com isto permita o retorno deles.



Lembre-se que este tipo de implementação - passagem de valor por referência - deve ser usado com cuidado, pois se você tiver vários valores que devem ser retornados em um método, o melhor seria a criação de uma Struct para retorná-los.
Então, voltando ao assunto do out e ref, vou mostrar trechos de código com a implementação de cada um:
Utilizando o out
  1. class OutExample
  2. {
  3.       // Separa uma string, que contém o primeiro e o último nome, em dois parâmetros que são passados por referência e que vão conter, respectivamente, o primeiro e o último nome.
  4.       static void SplitName(string fullName, out stringfirstName, out string lastName)
  5.       {
  6.             int spaceIndex = fullName.IndexOf(' ');
  7.             firstName = fullName.Substring(0, spaceIndex).Trim();
  8.             lastName = fullName.Substring(spaceIndex).Trim();
  9.       }
  10.       static void Main()
  11.       {
  12.             string fullName = "Yuan Sha";
  13.             string firstName;
  14.             string lastName;
  15.             // note que o firstName e o lastName não foram iniciados ainda, por que o parâmetro do tipo out nos garante isto.
  16.             SplitName(fullName, out firstName, outlastName);
  17.             System.Console.WriteLine("First Name '{0}'. Last Name '{1}'", firstName, lastName);
  18.       }
  19. }
E agora a implementação usando o parâmetro do tipo ref
  1. class RefExample
  2. {
  3.       static object FindNext(object value, object[]data, ref int index)
  4.       {
  5.             // veja que é possível acessar o index, pois ele foi instanciado
  6.             while (index < data.Length)
  7.             {
  8.                   if (data[index].Equals(value))
  9.                   {
  10.                         return data[index];
  11.                   }
  12.                    index += 1;
  13.             }
  14.              return null;
  15.       }
  16.       static void Main()
  17.       {
  18.             object[] data = new object[]{1,2,3,4,2,3,4,5,3};
  19.             int index = 0// deve ser inicializado antes de ser passado como parâmetro
  20.             while (FindNext(3, data, ref index) !=null)
  21.             {
  22.                   System.Console.WriteLine("Found at index {0}", index);
  23.                   index += 1;
  24.             }
  25.             System.Console.WriteLine("Done Find");
  26.       }
  27. }
Veja que a diferença entre os dois tipos de parâmetros são bem sutis. Na passagem utilizando out, não precisamos inicializar a variável que vamos passar, diferentemente quando implementamos o ref, onde somos obrigados a instancializá-la antes de passar o parâmetro.
Ambas fazem o mesmo papel, mas de acordo com as boas práticas de programação, o recomendado é a utilização do parâmetro por referência do tipo out.

Nenhum comentário:

Postar um comentário