2008-08-16 8 views

Respuesta

24

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 en el parámetro, y no la variable que se especificó.

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 parámetro out o ref se transmitirá a la persona que llama.

Tanto out y ref se comportan de forma idéntica excepto por una ligera diferencia: Es necesario ref parámetros a ser inicializado antes de llamar, mientras out parámetros pueden ser inicializadas. Por extensión, se garantiza que los parámetros ref se inicialicen al comienzo del método, mientras que los parámetros out 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 puntos cabo, la diferencia entre out y ref sólo es ejecutada por el compilador de C#, no por el CLR. Hasta donde yo sé, VB no tiene equivalente para out e implementa ref (como ByRef) solamente, haciendo coincidir el soporte del CLR.

+0

"copia de la referencia a ese objeto" o "referencia a la copia de ese objeto"? – bjan

3

out significa que el parámetro se inicializa mediante 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 la referencia subyacente a ser pasado:

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 
2

Una de mis propias preguntas en stackoverflow maneja este tema también.
Maneja aproximadamente "pass by reference" and "pass by value" en diferentes tipos de idiomas, c# is included así que tal vez pueda encontrar información adicional allí también.

Básicamente todo se reduce a:

  • ref: el parámetro con la palabra clave ref será pasado por referencia
  • a cabo: el parámetro con la palabra clave a cabo será tratado como un parámetro de salida

pero eso es realmente la respuesta más básica que puede dar, ya que es un poco más compleja de lo que se afirma aquí

7

Una nota adicional acerca de ref vs. out: La distinción entre los dos es impuesta por el compilador de C#. El CLR no distingue entre out y ref.Esto significa que no se puede tener dos métodos cuyas firmas se diferencian sólo por un cabo o 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) {} 
Cuestiones relacionadas