Eche un vistazo al siguiente programa:
class Test
{
List<int> myList = new List<int>();
public void TestMethod()
{
myList.Add(100);
myList.Add(50);
myList.Add(10);
ChangeList(myList);
foreach (int i in myList)
{
Console.WriteLine(i);
}
}
private void ChangeList(List<int> myList)
{
myList.Sort();
List<int> myList2 = new List<int>();
myList2.Add(3);
myList2.Add(4);
myList = myList2;
}
}
Supuse myListque habría pasado ref, y la salida sería
3
4
De hecho, la lista se "pasa por ref", pero solo la sortfunción tiene efecto. La siguiente declaración myList = myList2;no tiene ningún efecto.
Entonces la salida es de hecho:
10
50
100
¿Puedes ayudarme a explicar este comportamiento? Si de hecho myListno se pasa por referencia (como parece por myList = myList2no tener efecto), ¿cómo entra myList.Sort()en vigor?
Estaba asumiendo que incluso esa declaración no surtiría efecto y que el resultado sería:
100
50
10
c#
list
pass-by-reference
nmdr
fuente
fuente

ChangeListdevolver un enList<int>lugar de unvoidsi de hecho se está creando una nueva lista.Respuestas:
Está pasando una referencia a la lista , pero no está pasando la variable de lista por referencia , por lo que cuando llama
ChangeListal valor de la variable (es decir, la referencia, piense que se copia "puntero"), y cambia el valor de la el parámetro dentroChangeListno es visto porTestMethod.tratar:
Esto luego pasa una referencia a la variable local
myRef(como se declara enTestMethod); ahora, si reasigna el parámetro dentroChangeList, también está reasignando la variable dentroTestMethod.fuente
ChangeList, solo se copia la referencia : es el mismo objeto. Si cambia el objeto de alguna manera, todo lo que tenga una referencia a ese objeto verá el cambio.Inicialmente, se puede representar gráficamente de la siguiente manera:
Luego, se aplica la ordenación
myList.Sort();Finalmente, cuando lo hizo:,
myList' = myList2perdió el de la referencia pero no el original y la colección quedó ordenada.Si usa por referencia (
ref), entoncesmyList'ymyListse convertirá en el mismo (solo una referencia).Nota: utilizo
myList'para representar el parámetro que usa enChangeList(porque le dio el mismo nombre que el original)fuente
Aquí tienes una forma fácil de entenderlo.
Su lista es un objeto creado en montón. La variable
myListes una referencia a ese objeto.En C # nunca pasa objetos, pasa sus referencias por valor.
Cuando accede al objeto de lista a través de la referencia pasada en
ChangeList(mientras ordena, por ejemplo), la lista original cambia.La asignación en el
ChangeListmétodo se realiza al valor de la referencia, por lo tanto, no se realizan cambios en la lista original (todavía en el montón pero ya no se hace referencia a la variable del método).fuente
Este enlace lo ayudará a comprender el paso por referencia en C #. Básicamente, cuando un objeto de tipo de referencia se pasa por valor a un método, solo los métodos que están disponibles en ese objeto pueden modificar el contenido del objeto.
Por ejemplo, el método List.sort () cambia el contenido de la lista, pero si asigna algún otro objeto a la misma variable, esa asignación es local para ese método. Es por eso que myList permanece sin cambios.
Si pasamos un objeto de tipo de referencia usando la palabra clave ref, entonces podemos asignar algún otro objeto a la misma variable y eso cambia todo el objeto en sí.
(Editar: esta es la versión actualizada de la documentación vinculada anteriormente).
fuente
C # solo hace una copia superficial cuando pasa por valor a menos que el objeto en cuestión se ejecute
ICloneable(lo que aparentemente laListclase no lo hace).Lo que esto significa es que copia el
Listmismo, pero las referencias a los objetos dentro de la lista siguen siendo las mismas; es decir, los punteros continúan haciendo referencia a los mismos objetos que el originalList.Si cambia los valores de las cosas que sus nuevas
Listreferencias, también cambia el originalList(ya que hace referencia a los mismos objetos). Sin embargo, luego cambia lasmyListreferencias por completo a una nuevaList, y ahora solo la originalListhace referencia a esos números enteros.Lea la sección Pasando parámetros de tipo de referencia de este artículo de MSDN sobre "Pasando parámetros" para obtener más información.
"¿Cómo clono una lista genérica en C #" de StackOverflow habla sobre cómo hacer una copia profunda de una lista.
fuente
Si bien estoy de acuerdo con lo que todos han dicho anteriormente. Tengo una visión diferente de este código. Básicamente, está asignando la nueva lista a la variable local myList, no a la global. si cambia la firma de ChangeList (List myList) a Private void ChangeList () verá el resultado de 3, 4.
Aquí está mi razonamiento ... Aunque la lista se pasa por referencia, piense en ello como pasar una variable de puntero por valor. Cuando llama a ChangeList (myList), está pasando el puntero a (Global) myList. Ahora esto se almacena en la variable myList (local). Así que ahora su myList (local) y myList (global) apuntan a la misma lista. Ahora haces una ordenación => funciona porque (local) myList hace referencia a la myList original (global). A continuación, crea una nueva lista y asigna el puntero a esa myList (local). Pero tan pronto como la función sale, la variable myList (local) se destruye. HTH
fuente
Utilice la
refpalabra clave.Mire la referencia definitiva aquí para comprender los parámetros de paso.
Para ser específico, mire esto , para comprender el comportamiento del código.
EDITAR:
Sortfunciona sobre la misma referencia (que se pasa por valor) y, por lo tanto, los valores están ordenados. Sin embargo, asignar una nueva instancia al parámetro no funcionará porque el parámetro se pasa por valor, a menos que pongaref.Poner le
refpermite cambiar el puntero a la referencia a una nueva instancia deListen su caso. Sinref, puede trabajar en el parámetro existente, pero no puede hacer que apunte a otra cosa.fuente
Hay dos partes de memoria asignadas para un objeto de tipo de referencia. Uno en pila y otro en montón. La parte en la pila (también conocida como puntero) contiene una referencia a la parte en la pila, donde se almacenan los valores reales.
Cuando no se usa la palabra clave ref, solo se crea una copia de la parte en la pila y se pasa al método: referencia a la misma parte en el montón. Por lo tanto, si cambia algo en la parte del montón, esos cambios se mantendrán. Si cambia el puntero copiado, asignándolo para que haga referencia a otro lugar en el montón, no afectará al puntero de origen fuera del método.
fuente