2012-03-26 12 views
8

Tengo dos métodos:C# Paso tipo de referencia directamente vs parámetro out

public void A(List<int> nums) 
{ 
    nums.Add(10); 
} 

public void B(out List<int> nums) 
{ 
    nums.Add(10); 
} 

¿Cuál es la diferencia entre estas dos llamadas?

List<int> numsA = new List<int>(); 
A(numsA); 

List<int> numsB = new List<int>(); 
B(out numsB); 

En general, trato de entender la diferencia entre pasar tipos de referencia tal cual o como parámetros de salida.

Respuesta

0

La palabra clave out hace que los argumentos se pasen por referencia. Esto es similar a la palabra clave ref, excepto que la referencia requiere que la variable se inicialice antes de pasarla. Para usar un parámetro out, tanto la definición del método como el método de llamada deben usar explícitamente la palabra clave out . Por ejemplo:

http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx

6

En el ejemplo, el método B fallará para compilar, porque un parámetro out es considerado como no inicializado, así que hay que inicializarlo antes de poder utilizarlo. Además, cuando se llama a un método con un parámetro out, es necesario especificar la palabra clave out en el sitio de llamada:

B(out numsB); 

Y no es necesario para inicializar la variable numbsB antes de la llamada, ya que se sobrescribirá por el método.

Jon Skeet tiene un gran artículo que explica las diferentes maneras de pasar parámetros: Parameter passing in C#

0

En la versión B, la función tiene acceso directo a la variable. Es como la palabra clave 'ref', excepto que la variable debe asignarse desde dentro de la función que toma el parámetro. Le permite devolver múltiples valores de una función. Y la sintaxis de llamada es 'B (out numsB);'

3

Un parámetro sin ref, sin salida, como una variable local, denota una ubicación de almacenamiento. Si el tipo de ubicación de almacenamiento es un tipo de referencia, la ubicación de almacenamiento contiene una referencia a una instancia de ese tipo.

Los parámetros de referencia y de rechazo, por el contrario, mantienen una referencia a una ubicación de almacenamiento. Esa ubicación de almacenamiento podría ser una variable local, un campo o un elemento de matriz. En otras palabras, los parámetros ref y out presentan otra capa de indirección. Si tiene un parámetro ref o out de tipo referencia en un método, por lo tanto, representa una referencia a una referencia a un objeto.

¿Por qué querría una referencia a una referencia a un objeto? En caso de que necesite modificar la referencia al objeto (en lugar de modificar el objeto en sí).

Esta es una técnica útil en algunas circunstancias limitadas.Por ejemplo, es posible que desee escribir una función que ordena dos colas dependiendo de que tiene el valor más pequeño en la parte superior:

void OrderQueues(ref Queue<int> a, ref Queue<int> b) 
{ 
    if (a.Peek <= b.Peek) return; 
    var temp = a; 
    a = b; 
    b = temp; 
} 

Parámetros que son útiles si desea devolver más de un valor a partir de un método:

void OldestAndYoungest(IEnumerable<Person> people, out Person youngest, out Person oldest) 
{ 
    youngest = null; 
    oldest = null; 
    foreach (var person in people) 
    { 
     if (youngest == null || person.Age < youngest.Age) 
      youngest = person; 
     if (oldest == null || oldest.Age < person.Age) 
      oldest = person; 
    } 
} 

En mi experiencia, los parámetros de ref y out son bastante raros, y aún más raros con los tipos de referencia.

Tenga en cuenta que un parámetro ref debe ser inicializado por la persona que llama, mientras que un parámetro de salida debe ser inicializado por el destinatario. Si nunca le asigna un valor al parámetro ref, entonces probablemente debería ser un parámetro "normal". Si nunca le asigna un valor a un parámetro out, como en su ejemplo, su código no se compilará.

Cuestiones relacionadas