Pergunta

Qual é a diferença?Sempre uso ByVal, mas não tenho uma boa ideia de quando devo e quando não ...

Foi útil?

Solução

Se você passar uma referência, ao modificar o valor no método, a variável no site de chamada também será modificada.

Se você passar valor, é o mesmo que se outra variável fosse criada no método, então mesmo que você modifique, a variável original (no site da chamada) não terá seu valor alterado.

Então, de fato, você geralmente deve passar variáveis como valor.Passe como referência apenas se você tiver uma necessidade explícita de fazê-lo.

Outras dicas

ByRef= Você dá a seu amigo seu trabalho final (o original), ele o marca e pode devolvê-lo a você.

ByVal= Você deu a ele uma cópia do trabalho do termo e ele devolveu as alterações, mas você mesmo terá que colocá-las de volta no original.

O mais simples possível.

Por que usar Byref:
ByRef irá passar o PONTEIRO para o objeto que você está passando. Se você está no mesmo espaço de memória, isso significa passar apenas a 'palavra', não o objeto. O método para o qual você está passando pode fazer alterações no objeto original e não precisa passá-las de volta, pois estão no objeto original. Útil para agilizar a passagem de grandes volumes de dados. Você também pode usar ByRef para permitir o uso de um SUB em vez de uma FUNCTION (em VB), uma vez que não é necessário devolver o objeto.

Por que não usar o Byref:
Como o método tem acesso ao original, quaisquer alterações feitas serão imediatas e permanentes. Se o método falhar, o obleto pode ser corrompido. Usar ByVal fará uma cópia, passará a cópia inteira para o método, e então o método processará as informações e executará novamente uma cópia de volta, relatará as informações ou não fará nada.

ByRef é como um segundo valor de retorno.Ele passa uma referência ao objeto para a função, em vez do próprio objeto.Se você alterar o valor de um parâmetro ByRef na função, verá essas alterações após o término da função.Se isso não ficou claro o suficiente, leia isto e isso .

Sei que essa pergunta já foi respondida, mas queria apenas acrescentar o seguinte ...

O objeto que você passa para uma função está sujeito a ByRef / ByVal, entretanto, se esse objeto contém referências a outros objetos, eles podem ser modificados pelo método chamado independentemente de ByRef / ByVal.Explicação ruim, eu sei, veja o código abaixo para um melhor entendimento:

Public Sub Test()
    Dim testCase As List(Of String) = GetNewList()
    ByRefChange1(testCase)
    'testCase = Nothing
    testCase = GetNewList()

    ByValChange1(testCase)
    'testCase is unchanged
    testCase = GetNewList()

    ByRefChange2(testCase)
    'testCase contains the element "ByRef Change 2"
    testCase = GetNewList()

    ByValChange2(testCase)
    'testCase contains the element "ByVal Change 2"

End Sub

Public Function GetNewList() As List(Of String)
    Dim result As List(Of String) = New List(Of String)
    result.Add("Value A")
    result.Add("Value B")
    result.Add("Value C")
    Return result
End Function

Public Sub ByRefChange1(ByRef aList As List(Of String))
    aList = Nothing
End Sub

Public Sub ByValChange1(ByVal aList As List(Of String))
    aList = Nothing
End Sub

Public Sub ByRefChange2(ByRef aList As List(Of String))
    aList.Add("ByRef Change 2")
End Sub

Public Sub ByValChange2(ByVal aList As List(Of String))
    aList.Add("ByVal Change 2")
End Sub

EDITAR:

Além disso, considere se esta função foi chamada:

Public Sub ByValChange3(ByVal aList As List(Of String))
    aList.Add("ByVal Change 3")
    aList = New List(Of String)
    aList.Add("ByVal Change 4")
End Sub

O que acontece neste caso é que "ByVal Change 3" é adicionado à lista de chamadores, mas no ponto em que você especifica que "aList= New List" você está apontando a nova referência, para um novo objeto, e se separada lista de chamadores.Tanto o bom senso quanto podem te pegar um dia, então algo para ter em mente.

Espero que isso responda à sua pergunta

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

Acho que pode ter ocorrido um erro de digitação na última amostra: O último sub deve ser "byval" e não "byref".:)

Também foi adicionada uma instrução msgbox em try_byval para que você possa entender o que significa.

Sub begin()
Dim last_column As Integer

last_column = 234
MsgBox "Begin:" & last_column

trying_byref x:=last_column
MsgBox "byref:" & last_column

trying_byval v:=last_column
MsgBox "byval:" & last_column
End Sub

Sub trying_byref(ByRef x)
x = 111
End Sub

Sub trying_byval(ByVal v)  '<--not ByRef, that was in sub trying_byref.
v = 222
MsgBox "In Here:" & v
End Sub

ByRef, um valor terá 2 endereços

Então, se x= 80 (80 é o valor e x é o endereço, então, por exemplo, a variável y pode ser 80 também e, portanto, 80 pode ser acessada por x e y)

Respostas de @Tom e @kelloti são úteis.Aqui está um exemplo de código para ilustrar melhor:

Private Function ValMessage(ByVal SomeMessage As String)
    SomeMessage = "Val Val Val" ' <-- this variable modification doesn't persist after the function finishes execution
    ValMessage = "Some Return Value"
End Function

Private Function RefMessage(ByRef SomeMessage As String)
    SomeMessage = "Ref Ref Ref" ' <-- this variable modification persists even after the function finishes execution
    RefMessage = "Some Return Value"
End Function

Private Sub DoStuff()
    Dim OriginalMessage As String
    Dim OtherMessage As String
    Dim AnotherMessage As String

    OriginalMessage = "Original"
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"

    OtherMessage = ValMessage(OriginalMessage)
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"

    AnotherMessage = RefMessage(OriginalMessage)
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Ref Ref Ref" <--- this is the difference when you pass a paramter by reference
End Sub

Vou tentar explicar a diferença em palavras simples.

  • passar argumento por valor torna-o apenas parâmetro de entrada.Esta é a maneira mais segura, portanto, é usada por padrão em 95% dos casos.

  • passar argumento por referência torna-o parâmetro de entrada e saída.O parâmetro de saída pode ser alterado dentro da função, o que cria um efeito colateral raramente usado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top