Pergunta

Procuro uma resposta clara, concisa e precisa.

Idealmente, como a resposta real, embora sejam bem-vindos links para boas explicações.

Isso também se aplica ao VB.Net, mas as palavras-chave são diferentes - ByRef e ByVal.

Foi útil?

Solução

Por padrão (em C#), passar um objeto para uma função, na verdade, passa uma cópia da referência para esse objeto.Alterar o parâmetro em si altera apenas o valor do parâmetro, e não a variável que foi especificada.

void Test1(string param)
{
    param = "new value";
}

string s1 = "initial value";
Test1(s1);
// s1 == "initial value"

Usando out ou ref passa uma referência à variável especificada na chamada da função.Qualquer alteração no valor de um out ou ref parâmetro será passado de volta ao chamador.

Ambos out e ref comportar-se de forma idêntica, exceto por uma pequena diferença: ref parâmetros devem ser inicializados antes da chamada, enquanto out parâmetros podem ser não inicializados.Por extensão, ref os parâmetros são garantidos para serem inicializados no início do método, enquanto out parâmetros são tratados como não inicializados.

void Test2(ref string param)
{
    param = "new value";
}

void Test3(out string param)
{
    // Use of param here will not compile
    param = "another value";
}

string s2 = "initial value";
string s3;
Test2(ref s2);
// s2 == "new value"
// Test2(ref s3); // Passing ref s3 will not compile
Test3(out s2);
// s2 == "another value"
Test3(out s3);
// s3 == "another value"

Editar:Como DP aponta, a diferença entre out e ref é aplicado apenas pelo compilador C#, não pelo CLR.Até onde eu sei, VB não tem equivalente para out e implementos ref (como ByRef) apenas, correspondendo ao suporte do CLR.

Outras dicas

Uma observação adicional sobre ref vs.fora:A distinção entre os dois é imposta pelo compilador C#.O CLR não faz distinção entre out e ref.Isso significa que você não pode ter dois métodos cujas assinaturas diferem apenas por um out ou ref

void foo(int value) {}

// Only one of the following would be allowed

// valid to overload with ref
void foo(ref int value) {}

// OR with out
void foo(out int value) {}

out significa que o parâmetro será inicializado pelo método:

int result; //not initialised

if( int.TryParse( "123", out result ) )
   //result is now 123
else
   //if TryParse failed result has still be 
   // initialised to its default value (0)

ref forçará a referência subjacente a ser passada:

void ChangeMyClass1( MyClass input ) {
   input.MyProperty = "changed by 1";
   input = null;
   //can't see input anymore ... 
   // I've only nulled my local scope's reference
}

void ChangeMyClass2( ref MyClass input ) {
   input.MyProperty = "changed by 2";
   input = null;
   //the passed reference is now null too.
}

MyClass tester = new MyClass { MyProperty = "initial value" };

ChangeMyClass1( tester );
// now tester.MyProperty is "changed by 1"

ChangeMyClass2( ref tester );
// now tester is null

Uma das minhas perguntas no stackoverflow também aborda esse tópico.
Ele lida com cerca de "passagem por referência" e "passagem por valor" em diferentes tipos de idiomas, c# está incluído então talvez você também possa encontrar algumas informações extras lá.

Basicamente tudo se resume a:

  • referência:o parâmetro com a palavra-chave ref será passado por referência
  • fora:o parâmetro com a palavra-chave out será tratado como um parâmetro de saída

mas essa é realmente a resposta mais básica que você pode dar, pois é um pouco mais complexa do que é declarada aqui

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