Pergunta

Quais são as coisas a considerar ao escolher entre ByRef e ByVal.

Eu entendo a diferença entre os dois, mas eu não entendo completamente se ByRef economiza recursos ou se precisa mesmo se preocupar com isso no ambiente .Net.

Como você se decidir entre os dois, se a funcionalidade não importa em uma situação?

Foi útil?

Solução

Há um monte de cerca de desinformação sobre isso. A principal coisa é que você entenda a diferença entre tipos de valor e tipos de referência , eo diferença entre a passagem por valor e passar por referência.

Você quase sempre quer passar por valor. Passagem por referência é quase sempre para "Eu quero retornar mais de um resultado, e não apenas adicionando coisas para uma lista que é passado." O exemplo clássico de um método usando passagem por referência é Int32.TryParse onde o valor de retorno é um sucesso / fracasso, e o valor analisado é "devolvida" por um parâmetro de saída.

Outras dicas

O padrão é byValue para os tipos de tudo, mas é importante entender o que as duas opções significa para um "tipo de referência" (a classe), em oposição a um tipo de valor. (Estruturas).

Para um tipo de referência, se você declarar uma variável do tipo de referência em um método, essa variável é um local de memória no quadro de pilha do método. Não é na pilha. Quando você inicializa essa variável (usando novo ou uma fábrica, qualquer que seja), então você criou um objeto real na pilha, eo endereço desse objeto é armazenado na variável de referência declarado em seus métodos pilha quadro.

Quando você passar um tipo de referência para outro método ByVal, você está criando uma cópia do endereço armazenado nos métodos de chamada empilhar e passando a cópia desse valor (o endereço de ponteiro) para o método chamado, onde é armazenado em um novo slot de memória na chamada pilha métodos. Dentro do método chamado, os novos clonados variável aponta diretamente para o mesmo objeto na pilha. Então usá-lo pode alterar as propriedades do mesmo objeto. Mas você não pode mudar o que montão objeto a variável de referência original (sobre os métodos de chamada empilhar) aponta. Se, no chamado write método I

  myVar = new object();

A variável original no método de chamada não terá alterado para apontar para um novo objeto.

Se eu passar um tipo de referência ByRef, otoh, eu estou passando um ponteiro para a variável declarada nos métodos de chamada pilha (que contém um ponteiro para o objeto na pilha) É, portanto, um ponteiro para um ponteiro para o objeto . Ele aponta para o local de memória sobre os métodos de chamada pilha, que aponta para o objeto na pilha.
Então, agora, se eu mudar o valor da variável no método chamado, definindo-o como um novo objeto (), como acima, uma vez que é um "refereence" para a variável no método chamando, eu estou realmente mudando qual objeto a variável no método de chamada está apontando. Assim, após o chamado método retorna, a variável no método de chamada não será mais apontando para o mesmo objeto original na pilha.

ByVal deve ser seu "default". Usá-lo a menos que você tenha um motivo específico para usar ByRef

Passar um objeto ByVal em .net não faz uma cópia do objeto e não consome mais recursos, em seguida, ByRef, um ponteiro é ainda repassado para a função. O tempo de execução apenas garante que você não pode modificar o ponteiro em sua função e retornar um valor diferente para ele. Você ainda pode fazer alterações nos valores dentro do objeto e você vai ver essas mudanças fora da função. É por isso que ByRef é usos tão raramente. Ele só é necessário quando você quer uma função para alterar o objeto real que está voltando; portanto, um parâmetro de saída.

Use "ByRef" somente se o parâmetro é o parâmetro "output". Caso contrário, use "ByVal". Usando "ByRef" em parâmetros que explicitamente não deve retornar valores é perigoso e pode fácil gerar erros.

Eu diria que ByRef nunca deve ser usado - que é uma prática ruim. Gostaria de aplicar esse mesmo ao seu caso de uso típico de permitir uma função para retornar vários valores (via parâmetros ByRef). Seria melhor para a função para retornar uma resposta estruturada que inclui os vários valores de retorno. É mais claro e mais óbvio, se uma função retorna apenas valores através da sua instrução de retorno.

Marcação certos argumentos como ByRef mostra ao usuário da sua função que o variável atribuídos a esse argumento ** será modificado. ****

Se você usar ByRef para todos os argumentos, não haverá maneira de dizer quais variáveis ??são modificados pela função, e que são apenas lidos por ele. (para além de espreitar dentro da fonte da função!)

De acordo com a Microsoft, a escolha de ByVal ou ByRef pode afetar o desempenho de grandes valores suficientes (ver Passando argumentos por valor e por referência (Visual Basic) ):

Performance. Embora o mecanismo de passagem pode afetar o desempenho do seu código, a diferença é geralmente insignificante. uma exceção para isso é um tipo de valor passado ByVal. Neste caso, Visual Basic copia todo o conteúdo de dados do argumento. Portanto, para uma grande valor tipo, como uma estrutura, pode ser mais eficiente para passar -lo ByRef.

[grifo nosso].

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

Muita confusão Vou tentar simplificar. Você basicamente tem 4 opções:

  1. Passe um tipo de valor BYVAL
  2. Passe um tipo de valor ByRef
  3. Passe um objeto ByVal
  4. Passe um objeto ByRef

Algumas pessoas dizem que você deve não usar ByRef. Enquanto eles são tecnicamente correto, uma coisa é certa. Você deve NUNCA usar a palavra não . Se você está projetando um sistema a partir do zero, em seguida, ByRef devem ser evitados a todo custo. Usando ele expõe uma falha de projeto. No entanto trabalhando em um sistema existente pode não fornecer o máximo de flexability para implementar um bom design. Às vezes você deve fazer consessions, ou seja, usando ByRef. Por exemplo, se você pode obter uma correção no feito em 2 dias usando ByRef seguida, que pode ser preferível para re-inventar a roda e tendo uma semana para obter a mesma correção em apenas evitar o uso de ByRef.

Sumário:

  1. Usar ByVal em um tipo de valor: passa um valor para uma função. Esta é a forma preferida de funções de projeto.
  2. Usando ByRef em um tipo de valor: Útil para retornar mais de um valor de uma função. Se vocês estão criando uma função que precisa retornar mais de um valor para um sistema existente que pode ser melhor do que a criação de um objeto (e definição de propriedades, e eliminação) apenas para uma função.
  3. Usar ByVal em um objeto: passa um ponteiro de um objeto para uma função. A função pode modificar o objeto.
  4. Usando ByRef em um objeto: passa um ponteiro para um ponteiro de um objeto para uma função. permite alterar o objecto do chamador está a apontar para. Isso pode causar algum difícil encontrar erros e eu não consigo pensar em nenhuma boa razão para usá-lo. Não significa que há isnt, mas se houver eles são poucos e distantes entre si.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top