Desenvolvimento - Visual Basic

VB.NET: Entendendo Passagem por Valor e por Referência (Byval/ByRef)

O objetivo deste artigo é esclarecer uma dúvida muito comum em desenvolvedores que estão começando agora na linguagem Visual Basic e acabam não dando a devida atenção nas palavras-chave ByVal/ByRef (passagem de parâmetros por valor/Referêcia, respectivamente).

por Roberto Lopes



O objetivo deste artigo é esclarecer uma dúvida muito comum em desenvolvedores que estão começando agora na linguagem Visual Basic e acabam não dando a devida atenção nas palavras-chave ByVal/ByRef (passagem de parâmetros por valor/Referêcia, respectivamente).

Variáveis na Memória

Seja qual for a linguagem utilizada para desenvolver um programa, toda variável que criada é na verdade uma solicitação ao compilador para alocação de um determinado espaço na memória RAM do computador.

Quando o programa é executado, o endereço do local deste espaço reservado na memória é passado para esta variável. Será onde o conteúdo desta variável irá armazenar o seu conteúdo na memória.

A alocação da memória é efetuada de modo contínuo, isto é, se declaramos uma variável de 4 bytes, a alocação será efetuada no primeiro espaço de memória que tiver pelo menos 4 bytes livres. O endereço do primeiro byte será o endereço da variável na memória.

Transformando o texto acima em uma representação gráfica da memória, o conceito seria o equivalente ao apresentado na Figura 1, onde um espaço fictício de 6 bytes da memória é representado:


Figura 1: Visão da memória antes da criação da variável, onde cada linha representa um byte

Declararando uma variável do tipo Integer (System.Int32) e atribuindo um valor a ela (no exemplo 10), um espaço de 4 bytes de memória é alocado para esta variável:

Listagem 1 
Dim intVariavel As Integer 
intVariavel = 10

Na Figura 2, é apresentada a imagem da memória, após a declaração e atribuição de valor à variável:


Figura 2: Visão da memória depois da criação e atribuição de valor à variável.

Como já mencionado anteriormente, uma variável do tipo Integer possui tamanho de 4 bytes. Por isso, quatro posições de memória foram alocadas para esta variável: posições 1001, 1002, 1003 e 1004. Lembrando que não importa o valor atribuído a esta variável, ela sempre ocupará o espaço de 4 bytes na memória.

As Palavras-Chave ByVal e ByRef

Ok, agora que equalizamos o conceito de alocação de memória, vamos conceituar as palavras-chave ByVal e ByRef

Quando declaramos uma Sub ou Function no Visual Basic.Net, para cada parâmetro que é declarado, precisamos definir obrigatoriamente se vamos receber o parâmetro por valor (ByVal) ou por referência (ByRef). Na Listagem 2, uma Sub é declarada, recebendo um parâmetro por valor (veja a palavra-chave ByVal ao lado do parâmetro). Na Listagem 3, a mesma Sub é declarada, mas recebendo um parâmetro por referência (veja a palavra-chave ByRef ao lado do parâmetro):

Listagem 2
Private Sub exemplo(ByVal pParametro as Integer)
.
.
End Sub
Listagem 3
Private Sub exemplo(ByRef pParametro as Integer)
.
.
End Sub

Apenas três letras diferem a assinatura da Sub, mas fazem uma diferença e tanto no momento de utilizar as variáveis. Vamos entender porque.

ByVal

O que significa passar um valor por valor? É a passagem apenas do conteúdo da variável. Deste modo, o programa busca o que está contido no endereço da variável e este valor é enviado para a Sub. Se utilizarmos o nosso exemplo da Listagem 1, o valor 10 seria passado e pronto.

Tudo ficará muito mais claro depois que você entender o que vem a ser uma passagem por referência.

ByRef

Passar uma variável por referência seria ao invés de passar o conteúdo da variável, passarmos o endereço de memória da variável. Deste modo, se novamente utilizarmos nosso exemplo da Listagem 1, ao invés de passarmos 10, passariamos o endereço, que é 1001. Precisamos conhecer ou saber qual é o endereço da memória? Não. Tudo é gerenciado pelo Visual Basic. Você precisa apenas saber o que fazer com o parâmetro recebido.

ByVal ou ByRef?

Qual é a utilidade de enviar uma variável por referência ao invés de enviar por valor?

Quando passamos uma variável por valor, seja qual for o código executado na Sub ou na Function, o conteúdo da variável depois da execução permanecerá o mesmo, isto é, nada que for feito dentro da rotina vai alterar a variável na origem.

Quando passamos uma variável por referência, como estamos passando na verdade o endereço da variável, toda alteração que for realizada nesta variável, o conteúdo do endereço de memória passado por referência será modificado. Seria como se criássemos uma imagem de nossa variável, que qualquer alteração em qualquer dos pontos, irá refletir no outro.

Novamente utilizando o exemplo da Listagem 1, que contém o valor 10, se passarmos esta variável por referência e dentro desta Sub alterarmos o valor para 20, quando o programa voltar da Sub, como o conteúdo do endereço foi alterado, a variável intVariavel terá o valor 20.

Vamos ver toda essa teoria na prática.

Crie uma nova aplicação do tipo Visual Basic Windows Application no Visual Studio.Net. O nome da aplicação não importa, pode deixar todos os valores/nomes default.

Na classe Form1, coloque o código da Listagem 4 depois da Sub Form1_Load:

Private Sub TestaByVal(ByVal pParametro As Integer)
	pParametro = pParametro + 10
	"Resultado é 20
	MessageBox.Show(pParametro.ToString)
End Sub

Private Sub TestaByRef(ByRef pParametro As Integer)
	pParametro = pParametro + 10
	"Resultado é 20
	MessageBox.Show(pParametro.ToString)
End Sub	

Agora, adicione um botão ao formulário (novamente mantenha os valores default). No evento Click deste botão, adicione o código da Listagem 5:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
   Handles Button1.Click
   Dim intVariavel As Integer

   intVariavel = 10

   TestaByVal(intVariavel)
	"Resultado é 10, pois mesmo tendo sido modificado na Sub, foi passado por valor
   MessageBox.Show("Após a execução da Sub TestaByVal: " & intVariavel.ToString)

   TestaByRef(intVariavel)
   "Resultado é 20, pois foi passado por referência e foi modificado na Sub.
   MessageBox.Show("Após a execução da Sub TestaByRef: " & intVariavel.ToString)
End Sub

Também quero citar uma outra grande utilidade de passagens por referência, que supre uma carência quando precisamos de receber mais de um valor como resultado de uma Function. Neste caso, você pode utilizar uma Sub ou uma Function, passando as suas variáveis por referência e após concluída a Sub (ou Function), os valores das variáveis estarão atualizados.

Conclusão

Neste artigo, passei uma visão geral de como utilizar este grande recurso que temos em mãos no Visual Basic e em várias linguagens de programação é a possibilidade de decidir entre trabalhar apenas com os valores das variáveis ou o endereço da variável. Para quem já programou em C/C++, uma terminologia equivalente seria a de ponteiros.

Referências:

http://msdn.microsoft.com/vbasic/
http://www.codeproject.com
http://www.codeguru.com
http://www.builddevelopers.net

Roberto Lopes

Roberto Lopes - MCP em VB é consultor de desenvolvimento. Trabalhou em empresas como Grupo Citibank, Grupo Silvio Santos, Telesp, CST (Vixteam) e Senac-SP (também como instrutor). Atualmente é consultor de desenvolvimento VB/ASP.Net na empresa CGI Inc. em Toronto/Canada.