Passe a ref
se você deseja alterar qual é o objeto:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
Depois de chamar DoSomething, t
não se refere ao original new TestRef
, mas se refere a um objeto completamente diferente.
Isso também pode ser útil se você quiser alterar o valor de um objeto imutável, por exemplo, a string
. Você não pode alterar o valor de uma string
depois que ele foi criado. Mas, usando a ref
, você pode criar uma função que altera a string para outra que tenha um valor diferente.
Edit: Como outras pessoas mencionaram. Não é uma boa ideia usar a ref
menos que seja necessário. O uso ref
dá ao método a liberdade de alterar o argumento para outra coisa, os chamadores do método precisarão ser codificados para garantir que eles manejem essa possibilidade.
Além disso, quando o tipo de parâmetro é um objeto, as variáveis de objeto sempre atuam como referências ao objeto. Isso significa que, quando a ref
palavra-chave é usada, você tem uma referência a uma referência. Isso permite que você faça as coisas conforme descrito no exemplo acima. Mas, quando o tipo de parâmetro é um valor primitivo (por exemplo int
), se esse parâmetro for atribuído ao método, o valor do argumento que foi passado será alterado após o retorno do método:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
ref
no site da chamada ... onde mais você gostaria que fosse distinguido? A semântica também é razoavelmente clara, mas precisa ser expressa com cuidado (em vez de "objetos são passados por referência", que é a simplificação excessiva comum).No .NET, quando você passa qualquer parâmetro para um método, uma cópia é criada. Nos tipos de valor, significa que qualquer modificação feita no valor está no escopo do método e é perdida quando você sai do método.
Ao passar um Tipo de Referência, também é feita uma cópia, mas é uma cópia de uma referência, ou seja, agora você tem DUAS referências na memória para o mesmo objeto. Portanto, se você usar a referência para modificar o objeto, ele será modificado. Mas se você modificar a própria referência - devemos lembrar que é uma cópia -, quaisquer alterações também serão perdidas ao sair do método.
Como as pessoas disseram anteriormente, uma atribuição é uma modificação da referência, portanto, é perdida:
Os métodos acima não modificam o objeto original.
Uma pequena modificação do seu exemplo
fonte
Como TestRef é uma classe (que são objetos de referência), você pode alterar o conteúdo dentro de t sem passar como ref. No entanto, se você passar t como ref, TestRef poderá alterar a que t original se refere. ou seja, faça apontar para um objeto diferente.
fonte
Com
ref
você pode escrever:E t será alterado após a conclusão do método.
fonte
Pense nas variáveis (por exemplo
foo
) dos tipos de referência (por exemploList<T>
) como contendo identificadores de objeto no formato "Objeto # 24601". Suponha que a instruçãofoo = new List<int> {1,5,7,9};
façafoo
com que o objeto "Objeto # 24601" (uma lista com quatro itens). A chamadafoo.Length
pedirá o comprimento do objeto nº 24601 e responderá 4, sendofoo.Length
igual a 4.Se
foo
for passado para um método sem usarref
, esse método poderá fazer alterações no Objeto # 24601. Como conseqüência de tais alterações,foo.Length
pode não ser mais igual a 4. O próprio método, no entanto, não poderá ser alteradofoo
, o que continuará mantendo o "Objeto # 24601".Passar
foo
comoref
parâmetro permitirá que o método chamado faça alterações não apenas no Objeto # 24601, mas também emfoo
si mesmo. O método pode criar um novo Objeto # 8675309 e armazenar uma referência a isso emfoo
. Se isso acontecer,foo
não conteria mais "Objeto nº 24601", mas sim "Objeto # 8675309".Na prática, as variáveis do tipo de referência não contêm seqüências de caracteres do formulário "Object # 8675309"; eles nem guardam nada que possa ser convertido significativamente em um número. Embora cada variável do tipo de referência mantenha algum padrão de bits, não há relacionamento fixo entre os padrões de bits armazenados nessas variáveis e os objetos que eles identificam. Não há como o código extrair informações de um objeto ou uma referência a ele e, posteriormente, determinar se outra referência identificou o mesmo objeto, a menos que o código contenha ou soubesse de uma referência que identificasse o objeto original.
fonte
É como passar um ponteiro para um ponteiro em C. No .NET, isso permitirá que você altere o que o T original se refere, pessoalmente , embora eu pense que, se você estiver fazendo isso no .NET, provavelmente terá um problema de design!
fonte
Usando a
ref
palavra-chave com tipos de referência, você está efetivamente passando uma referência para a referência. De muitas maneiras, é o mesmo que usar aout
palavra - chave, mas com a pequena diferença de que não há garantia de que o método realmente atribua algo aoref
parâmetro 'ed.fonte
ref
imita (ou se comporta) como uma área global apenas por dois escopos:fonte
Se você está passando um valor, no entanto, as coisas são diferentes. Você pode forçar um valor a ser passado por referência. Isso permite que você passe um número inteiro para um método, por exemplo, e faça com que o método modifique o número inteiro em seu nome.
fonte
Ref indica se a função pode colocar as mãos no próprio objeto ou apenas em seu valor.
Passar por referência não está vinculado a um idioma; é uma estratégia de ligação de parâmetro ao lado de passar por valor, passar por nome, passar por necessidade etc ...
Uma nota lateral: o nome da classe
TestRef
é uma escolha horrivelmente ruim nesse contexto;).fonte