Paso por valor frente a paso por referencia — RexDac Academy

RexDac AcademyNotas técnicas · Ayuda tener algunos conocimientos previos
0%Notas publicadas leídas · en este dispositivo

Nivel 3 — Funciones

Paso por valor frente a paso por referencia

Notas originales de SunDiaL · Ver fuente en inglés

Segunda parte de esta saga confusa. Los parámetros también se dividen en dos categorías que, combinadas con los tipos de valor y los tipos de referencia, dan un total de cuatro combinaciones.

Paso por valor

Esta es la forma estándar de pasar parámetros. A la variable del parámetro se le asigna una copia del valor.

  • Para los tipos de valor, esto significa que se copia el propio valor.
  • Para los tipos de referencia, esto significa que se copia la dirección del objeto. Es lo mismo que pasar por puntero en C++.

Paso por referencia

La otra forma de pasar parámetros.

  • En este caso, el objeto se utiliza «directamente». Es lo mismo que pasar por referencia en C++; sin embargo, las referencias en C# no son exactamente lo mismo que las referencias en C++.

    Para una explicación más detallada sobre las referencias de C++, consulta Puntero frente a referencia.

Es difícil de explicar sin verlo en acción, y para eso hace falta conocer las clases, así que vuelve a estos ejemplos más adelante.

Ejemplos

1. Tipo de valor por valor

void ByVal(int x)
{
	x++;
	Console.WriteLine(x);
}

void Main()
{
	int x = 1; 
	ByVal(x); // will print 2
	Console.WriteLine(x); //will print 1, because there are now two "1" objects sitting in memory. One for the x in main, and one for the x in ByVal.
}

2. Tipo de valor por referencia

void ByRef(ref int x)
{
	x++;
	Console.WriteLine(x);
}

void Main()
{
	int x = 1; 
	ByVal(ref x); // will print 2
	Console.WriteLine(x); //will print 2, because x in ByRef uses the the object itself, not a copy.
}

3. Tipo de referencia por valor

class Test
{
	public int val;
}
void ByValIncrement(Test x)
{
	x.val++
	Console.WriteLine(x.val);
}

void ByValIncrement(Test x)
{
	x = new Test();
	x.val = 3;
	Console.WriteLine(x.val);
}

void Main()
{
	Test x = new Test();
	x.val = 1;
	ByValIncrement(x); // will print 2
	Console.WriteLine(x.val); //will print 2, because the same address was used.
	
	ByValChange(x) //will print 3.
	Console.WriteLine(x.val); //will print 2, because the object was changed inside the function. 	
}

4. Tipo de referencia por referencia

class Test
{
	public int val;
}
void ByValIncrement(ref Test x)
{
	x.val++
	Console.WriteLine(x.val);
}

void ByValIncrement(ref Test x)
{
	x = new Test();
	x.val = 3;
	Console.WriteLine(x.val);
}

void Main()
{
	Test x = new Test();
	x.val = 1;
	ByValIncrement(ref x); // will print 2
	Console.WriteLine(x.val); //will print 2, because the same object was used.
	
	ByValChange(ref x) //will print 3.
	Console.WriteLine(x.val); //will print 3, because the object was used "directly".
}