Em C #, sempre pensei que variáveis não primitivas fossem passadas por referência e valores primitivos passados por valor.
Portanto, ao passar para um método qualquer objeto não primitivo, qualquer coisa feita ao objeto no método afetará o objeto que está sendo passado. (Material C # 101)
No entanto, notei que, quando passo um objeto System.Drawing.Image, isso não parece ser o caso? Se eu passar um objeto system.drawing.image para outro método e carregar uma imagem nesse objeto, deixe esse método sair do escopo e voltar ao método de chamada, essa imagem não será carregada no objeto original?
Por que é isso?
Respostas:
Objetos não são passados. Por padrão, o argumento é avaliado e seu valor é passado, por valor, como o valor inicial do parâmetro do método que você está chamando. Agora, o ponto importante é que o valor é uma referência para tipos de referência - uma maneira de chegar a um objeto (ou nulo). As alterações nesse objeto serão visíveis no chamador. No entanto, alterar o valor do parâmetro para se referir a um objeto diferente não será visível quando você estiver usando a passagem por valor, que é o padrão para todos os tipos.
Se você deseja usar passagem por referência, deve usar
out
ouref
, se o tipo de parâmetro é um tipo de valor ou um tipo de referência. Nesse caso, efetivamente a variável em si é passada por referência; portanto, o parâmetro usa o mesmo local de armazenamento que o argumento - e as alterações no próprio parâmetro são vistas pelo chamador.Assim:
Eu tenho um artigo que entra em muito mais detalhes nisso . Basicamente, "passar por referência" não significa o que você pensa que significa.
fonte
ref
- chave eout
do c #, não há problema em dizer que o c # passa parâmetros da mesma maneira que o java, ou seja, sempre por valor. Existe alguma diferença com o java.Mais um exemplo de código para mostrar isso:
E a saída:
fonte
Muitas boas respostas foram adicionadas. Eu ainda quero contribuir, pode ser que esclareça um pouco mais.
Quando você passa uma instância como argumento para o método, ela passa a
copy
da instância. Agora, se a instância que você passa é avalue type
(reside emstack
), você passa a cópia desse valor; portanto, se você o modificar, ele não será refletido no chamador. Se a instância for um tipo de referência, você passa a cópia da referência (novamente reside emstack
) para o objeto. Então você tem duas referências ao mesmo objeto. Ambos podem modificar o objeto. Mas se, no corpo do método, você instancia um novo objeto, sua cópia da referência não se refere mais ao objeto original, mas ao novo objeto que você acabou de criar. Então você terá 2 referências e 2 objetos.fonte
Eu acho que é mais claro quando você faz assim. Eu recomendo baixar o LinqPad para testar coisas como esta.
E isso deve gerar
WontUpdate
Nome: Egli, Sobrenome: Becerra
UpdateImplicitly
Nome: Favio, Sobrenome: Becerra
UpdateExplicitly
Nome: Favio, Sobrenome: Becerra
fonte
Quando você passa o
System.Drawing.Image
objeto de tipo para um método, na verdade está passando uma cópia da referência a esse objeto.Portanto, se dentro desse método você estiver carregando uma nova imagem, você estará carregando usando uma referência nova / copiada. Você não está fazendo alterações no original.
fonte
Como você passou o objeto para o método?
Você está fazendo novo dentro desse método para objeto? Nesse caso, você deve usar o
ref
métodoO link a seguir dá uma idéia melhor.
http://dotnetstep.blogspot.com/2008/09/passing-reference-type-byval-or-byref.html
fonte
Na passagem por referência Você apenas adiciona "ref" nos parâmetros da função e mais uma coisa que deve declarar a função "estática" porque main é estático (#
public void main(String[] args)
)!fonte