Pregunta

Busco una respuesta clara, concisa y precisa.

Idealmente como la respuesta real, aunque se aceptan enlaces a buenas explicaciones.

Esto también se aplica a VB.Net, pero las palabras clave son diferentes: ByRef y ByVal.

¿Fue útil?

Solución

De forma predeterminada (en C#), pasar un objeto a una función en realidad pasa una copia de la referencia a ese objeto.Cambiar el parámetro en sí solo cambia el valor del parámetro y no la variable especificada.

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

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

Usando out o ref pasa una referencia a la variable especificada en la llamada a la función.Cualquier cambio en el valor de un out o ref El parámetro se devolverá a la persona que llama.

Ambos out y ref comportarse de manera idéntica excepto por una pequeña diferencia: ref Los parámetros deben inicializarse antes de llamar, mientras que out Los parámetros se pueden desinicializar.Por extensión, ref Se garantiza que los parámetros se inicializarán al inicio del método, mientras que out Los parámetros se tratan como no 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 señala, la diferencia entre out y ref solo lo aplica el compilador de C#, no el CLR.Hasta donde yo sé, VB no tiene equivalente para out e implementos ref (como ByRef) únicamente, coincidiendo con el soporte del CLR.

Otros consejos

Una nota adicional sobre árbitro vs.afuera:La distinción entre los dos la aplica el compilador de C#.El CLR no distingue entre out y ref.Esto significa que no puede tener dos métodos cuyas firmas difieran solo por una salida o una referencia.

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 el parámetro será inicializado por el 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 obligará a pasar la referencia subyacente:

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

Una de mis propias preguntas en stackoverflow también aborda este tema.
Se maneja sobre "pasar por referencia" y "pasar por valor" en diferentes tipos de idiomas, c# está incluido Entonces tal vez puedas encontrar información adicional allí también.

Básicamente todo se reduce a:

  • árbitro:se pasará el parámetro con la palabra clave ref por referencia
  • afuera:el parámetro con la palabra clave out será tratado como un parámetro de salida

pero esa es realmente la respuesta más básica que puedes dar, ya que es un poco más compleja de lo que se indica aquí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top