Pregunta

entiendo que si paso a-tipo de valor (int, struct, etc.) como un parámetro (sin la palabra clave ref), una copia de esa variable se pasa al método, pero si uso el ref palabra clave una se pasa referencia a esa variable, no es nuevo.

Sin embargo, con referencia tipos, como las clases, incluso sin la palabra clave ref, una referencia se pasa al método, no una copia. Entonces, ¿cuál es el uso de la palabra clave ref con referencia tipos?


Tomemos, por ejemplo:

var x = new Foo();

¿Cuál es la diferencia entre lo siguiente?

void Bar(Foo y) {
    y.Name = "2";
}

y

void Bar(ref Foo y) {
    y.Name = "2";
}
¿Fue útil?

Solución

Puede cambiar lo foo puntos a utilizar y:

Foo foo = new Foo("1");

void Bar(ref Foo y)
{
    y = new Foo("2");
}

Bar(ref foo);
// foo.Name == "2"

Otros consejos

Hay casos en los que desee modificar el real referencia y no con el objeto apuntado:

void Swap<T>(ref T x, ref T y) {
    T t = x;
    x = y;
    y = t;
}

var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);

Jon Skeet escribió un gran artículo sobre el traspaso de parámetros en C #. Se detalla claramente el comportamiento exacto y el uso de paso de parámetros por valor, por referencia (ref), y por la salida (out).

Aquí hay un presupuesto importante de esa página en relación con los parámetros ref:

  

Parámetros de referencia no pasan la   valores de las variables utilizadas en el   miembro de la función de invocación - que utilizan   las variables mismas. Más bien que   la creación de una nueva ubicación de almacenamiento para   la variable en la función miembro   declaración, la misma ubicación de almacenamiento   se utiliza, por lo que el valor de la variable   en el miembro de función y el valor   del parámetro de referencia será siempre   ser el mismo. parámetros de referencia necesitan   el modificador ref como parte tanto de la   declaración y la invocación - que   significa que siempre es clara cuando estás   pasando algo por referencia.

Muy bien explicado aquí: http://msdn.microsoft.com/en-us/library/s6938f28.aspx

Extracto del artículo:

  

Una variable de un tipo de referencia no contiene sus datos directamente; eso   contiene una referencia a sus datos. Cuando se pasa una referencia de tipo   parámetro por valor, es posible cambiar los datos apuntado por   la referencia, tales como el valor de un miembro de la clase. Sin embargo,   no puede cambiar el valor de la referencia en sí; es decir, no se puede   utilizar la misma referencia para asignar memoria para una nueva clase y tenerlo   persistir fuera del bloque. Para ello, pase el parámetro utilizando el   ref o palabra clave a cabo.

Cuando se pasa un tipo de referencia con la palabra clave ref, se pasa la referencia por referencia, y el método se llama puede asignar un nuevo valor al parámetro. Ese cambio se propagará al alcance llamando. Sin ref, la referencia se pasa por valor, y esto no sucede.

C # también tiene la palabra clave 'hacia fuera', que se parece mucho a ref, excepto que con 'ref', los argumentos deben inicializarse antes de llamar al método, y con 'hacia fuera' se debe asignar un valor en el método de recepción.

Se le permite modificar la referencia aprobada en. Por ejemplo.

void Bar()
{
    var y = new Foo();
    Baz(ref y);
}

void Baz(ref Foo y)
{
    y.Name = "2";

    // Overwrite the reference
    y = new Foo();
}

También puede utilizar a cabo si no se preocupan por la referencia aprobada en:

void Bar()
{
    var y = new Foo();
    Baz(out y);
}

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}

Otro montón de código

class O
{
    public int prop = 0;
}

class Program
{
    static void Main(string[] args)
    {
        O o1 = new O();
        o1.prop = 1;

        O o2 = new O();
        o2.prop = 2;

        o1modifier(o1);
        o2modifier(ref o2);

        Console.WriteLine("1 : " + o1.prop.ToString());
        Console.WriteLine("2 : " + o2.prop.ToString());
        Console.ReadLine();
    }

    static void o1modifier(O o)
    {
        o = new O();
        o.prop = 3;
    }

    static void o2modifier(ref O o)
    {
        o = new O();
        o.prop = 4;
    }
}

Además de las respuestas existentes:

A medida que solicitó la diferencia de los métodos 2: No hay co (tra) varianza al utilizar ref o out:

class Foo { }
class FooBar : Foo { }

static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }

void Main()
{
    Foo foo = null;
    Bar(foo);           // OK
    Bar(ref foo);       // OK

    FooBar fooBar = null;
    Bar(fooBar);        // OK (covariance)
    Bar(ref fooBar);    // compile time error
}

Un parámetro en un método parece estar pasando siempre una copia, la cuestión es una copia de lo. Una copia se realiza mediante un constructor de copia de un objeto y que todas las variables son objetos en C #, creo que este es el caso para todos ellos. Las variables (objetos) son como las personas que viven en algunas direcciones. O nos cambiamos las personas que viven en esas direcciones o podemos crear más referencias a las personas que viven en las direcciones de la libreta de teléfonos (hacer copias de poca profundidad). Así, más de un identificador puede hacer referencia a la misma dirección. Tipos de referencia desear más espacio, por lo que a diferencia de los tipos de valor que están directamente conectados por una flecha a su identificador en la pila, que tienen valor para otra dirección en el montón (un espacio más grande para habitar). Este espacio necesita ser tomada de la pila.

Tipo de valor: Indentifier (contiene value = dirección del valor de la pila) ----> Valor de tipo de valor

Tipo de referencia: Identificador (contiene value = dirección del valor de la pila) ----> (contiene value = dirección del valor montón) ----> valor Heap (más a menudo contiene direcciones de otros valores), imaginar más flechas que se pega en diferentes direcciones a la matriz [0], array [1], array [2]

La única manera de cambiar un valor es seguir las flechas. Si una flecha se pierde / cambiado en la forma en que el valor es inalcanzable.

Las variables de referencia llevan la dirección de un lugar a otro por lo que cualquier updation en ellos en cualquier lugar se reflejará en todos los lugares entonces ¿cuál es el uso de REF. variable de referencia (405) son buenas hasta que ningún nuevo la memoria se asigna a la variable de referencia pasado en el método.

Una vez nueva memoria asignar (410), entonces el cambio de valor en este objeto (408) no reflejará en todas partes. Por esta ref viene. Ref es la referencia de referencia de modo que cada vez que la nueva memoria asignar llegar a conocer, ya que apunta a ese lugar, por tanto, el valor puede ser compartida por todos. Se puede ver la imagen para más clearity.

Ref la variable de referencia

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