Passando argumentos por valor e por referência (Visual Basic)

No Visual Basic, você pode passar um argumento para um procedimento por valor ou por referência. Isso é conhecido como o mecanismo de passagem e determina se o procedimento pode modificar o elemento de programação subjacente ao argumento no código de chamada. A declaração de procedimento determina o mecanismo de passagem para cada parâmetro especificando a palavra-chave ByVal ou ByRef.

Distinções

Ao passar um argumento para um procedimento, lembre-se de várias distinções diferentes que interagem entre si:

  • Se o elemento de programação subjacente é modificável ou não modificável

  • Se o argumento em si é modificável ou não modificável

  • Se o argumento está sendo passado por valor ou por referência

  • Se o tipo de dados de argumento é um tipo de valor ou um tipo de referência

Para obter mais informações, consulte Diferenças entre argumentos modificáveis e não modificáveis e diferenças entre passar um argumento por valor e por referência.

Escolha do mecanismo de passagem

Você deve escolher o mecanismo de passagem cuidadosamente para cada argumento.

  • Proteção. Ao escolher entre os dois mecanismos de passagem, o critério mais importante é a exposição de variáveis de chamada a serem alteradas. A vantagem de passar um argumento ByRef é que o procedimento pode retornar um valor para o código de chamada por meio desse argumento. A vantagem de passar um argumento ByVal é que ele protege uma variável de ser alterada pelo procedimento.

  • Desempenho. Embora o mecanismo de passagem possa afetar o desempenho do código, a diferença geralmente é insignificante. Uma exceção a isso é um tipo de valor passado ByVal. Nesse caso, o Visual Basic copia todo o conteúdo de dados do argumento. Portanto, para um tipo de valor grande, como uma estrutura, pode ser mais eficiente passá-la ByRef.

    Para tipos de referência, somente o ponteiro para os dados é copiado (quatro bytes em plataformas de 32 bits, oito bytes em plataformas de 64 bits). Portanto, você pode passar argumentos de tipo String ou Object por valor sem prejudicar o desempenho.

Determinação do mecanismo de passagem

A declaração de procedimento especifica o mecanismo de passagem para cada parâmetro. O código de chamada não pode substituir um ByVal mecanismo.

Se um parâmetro for declarado com ByRef, o código de chamada poderá forçar o mecanismo colocando ByVal o nome do argumento em parênteses na chamada. Para mais informações, confira Como forçar um argumento a ser passado por Valor.

O padrão no Visual Basic é passar argumentos por valor.

Quando passar um argumento por valor

  • Se o elemento de código de chamada subjacente ao argumento for um elemento não modificável, declare o parâmetro correspondente ByVal. Nenhum código pode alterar o valor de um elemento não modificável.

  • Se o elemento subjacente for modificável, mas você não quiser que o procedimento seja capaz de alterar seu valor, declare o parâmetro ByVal. Somente o código de chamada pode alterar o valor de um elemento modificável passado por valor.

Quando passar um argumento por referência

  • Se o procedimento tiver uma necessidade genuína de alterar o elemento subjacente no código de chamada, declare o parâmetro correspondente ByRef.

  • Se a execução correta do código depender do procedimento que altera o elemento subjacente no código de chamada, declare o parâmetro ByRef. Se você passá-lo por valor ou se o código de chamada substituir o ByRef mecanismo de passagem colocando o argumento entre parênteses, a chamada de procedimento poderá produzir resultados inesperados.

Exemplo

Descrição

O exemplo a seguir ilustra quando passar argumentos por valor e quando passá-los por referência. O procedimento Calculate tem um parâmetro e um ByValByRef parâmetro. Dada uma taxa de juros, ratee uma soma de dinheiro, debta tarefa do procedimento é calcular um novo valor para debt isso é o resultado da aplicação da taxa de juros ao valor original de debt. Como debt é um ByRef parâmetro, o novo total é refletido no valor do argumento no código de chamada que corresponde a debt. O parâmetro rate é um ByVal parâmetro porque Calculate não deve alterar seu valor.

Código

Module Module1

    Sub Main()
        ' Two interest rates are declared, one a constant and one a 
        ' variable.
        Const highRate As Double = 12.5
        Dim lowRate = highRate * 0.6

        Dim initialDebt = 4999.99
        ' Make a copy of the original value of the debt.
        Dim debtWithInterest = initialDebt

        ' Calculate the total debt with the high interest rate applied.
        ' Argument highRate is a constant, which is appropriate for a 
        ' ByVal parameter. Argument debtWithInterest must be a variable
        ' because the procedure will change its value to the calculated
        ' total with interest applied.
        Calculate(highRate, debtWithInterest)
        ' Format the result to represent currency, and display it.
        Dim debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with high interest: " & debtString)

        ' Repeat the process with lowRate. Argument lowRate is not a 
        ' constant, but the ByVal parameter protects it from accidental
        ' or intentional change by the procedure. 

        ' Set debtWithInterest back to the original value.
        debtWithInterest = initialDebt
        Calculate(lowRate, debtWithInterest)
        debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with low interest:  " & debtString)
    End Sub

    ' Parameter rate is a ByVal parameter because the procedure should
    ' not change the value of the corresponding argument in the 
    ' calling code. 

    ' The calculated value of the debt parameter, however, should be
    ' reflected in the value of the corresponding argument in the 
    ' calling code. Therefore, it must be declared ByRef. 
    Sub Calculate(ByVal rate As Double, ByRef debt As Double)
        debt = debt + (debt * rate / 100)
    End Sub

End Module

Confira também