Ejercicio: Usar parámetros de tipo de valor y referencia
En C#, las variables se pueden clasificar en dos tipos principales, tipos de valor y tipos de referencia. Estos tipos describen cómo las variables almacenan sus valores.
Los tipos de valor como int, bool, float, doubley char contienen directamente valores. Los tipos de referencia como string, arrayy objetos (como instancias de Random) no almacenan sus valores directamente. En su lugar, los tipos de referencia almacenan una dirección donde se almacena su valor.
Parámetros pasados por valor y pasados por referencia
Cuando se pasa un argumento a un método, las variables de tipo de valor tienen sus valores copiados en el método . Cada variable tiene su propia copia del valor, por lo que la variable original no se modifica.
Con los tipos de referencia, la dirección del valor se pasa al método . La variable dada al método hace referencia al valor en esa dirección, por lo que las operaciones en esa variable afectan al valor al que hace referencia el otro.
Nota:
Es importante recordar que string es un tipo de referencia, pero es inmutable. Esto significa que una vez que se le ha asignado un valor, no se puede modificar. En C#, cuando se usan métodos y operadores para modificar una cadena, el resultado que se devuelve es realmente un nuevo objeto de cadena.
En este ejercicio, obtendrá más información sobre cómo pasar argumentos de tipo de referencia y valor a métodos.
Prueba de paso por valor
En el editor de Visual Studio Code, elimine cualquier código que haya de los ejercicios anteriores.
En el Editor de Visual Studio Code, escriba el código siguiente:
int a = 3; int b = 4; int c = 0; Multiply(a, b, c); Console.WriteLine($"global statement: {a} x {b} = {c}"); void Multiply(int a, int b, int c) { c = a * b; Console.WriteLine($"inside Multiply method: {a} x {b} = {c}"); }Las variables
a,bycse pasan alMultiplymétodo . Los valores de las variables se imprimen durante la ejecución del método e imprimen de nuevo una vez completado el método.Los enteros son tipos de valor, que tienen sus valores copiados cuando se pasan a métodos. ¿Qué crees que será la salida de
c?Guarde y ejecute el código para observar la salida siguiente:
inside Multiply method: 3 x 4 = 12 global statement: 3 x 4 = 0Observe que el valor de
csolo se modifica dentro delMultiplymétodo . Fuera del método,cconserva su valor original.
Prueba de paso por referencia
Elimine el código anterior del Editor de Visual Studio Code.
En el Editor de Visual Studio Code, escriba el código siguiente:
int[] array = {1, 2, 3, 4, 5}; PrintArray(array); Clear(array); PrintArray(array); void PrintArray(int[] array) { foreach (int a in array) { Console.Write($"{a} "); } Console.WriteLine(); } void Clear(int[] array) { for (int i = 0; i < array.Length; i++) { array[i] = 0; } }El código comienza con
arrayinicializado para contener algunos valores enteros. Los valores se muestran mediante elPrintArraymétodo . Se llama al métodoClearen la matriz y luego se imprime la matriz de nuevo.Las matrices son tipos de referencia. Los tipos de referencia almacenan la dirección de sus valores en memoria. ¿Qué crees que será el resultado?
Guarde y ejecute el código para observar la salida siguiente:
1 2 3 4 5 0 0 0 0 0Observe que la matriz permanece modificada fuera del ámbito del
Clearmétodo. Esto sucede porque elClearmétodo actualizó los valores almacenados en cada dirección.
Prueba con cadenas
Anteriormente, aprendiste que las cadenas son de tipo inmutable. Aunque una cadena es un tipo de referencia, a diferencia de una matriz, su valor no se puede modificar una vez asignado. Es posible que haya observado esto si ha usado métodos como string.Replace o string.ToUpper. En esta tarea, aprenderá a corregir un error común encontrado al trabajar con cadenas.
En el editor de Visual Studio Code, elimine cualquier código que haya de los ejercicios anteriores.
En el Editor de Visual Studio Code, escriba el código siguiente:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(status, false); Console.WriteLine($"End: {status}"); void SetHealth(string status, bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }Guarde y ejecute el código para observar la salida siguiente:
Start: Healthy Middle: Unhealthy End: HealthySi el
SetHealthmétodo no ha generado el estado, es posible que haya asumido que el método no se ejecutó correctamente. En su lugar, se ha creado una cadena con el valor "Incorrecto" que se ha perdido en el ámbito del método.Para corregir este problema, puede cambiar
SetHealthpara usar la variable de estado global en su lugar.Actualice el código de la manera siguiente:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(false); Console.WriteLine($"End: {status}"); void SetHealth(bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }En este código, sobrescribe la variable global
statuscon el nuevo valor de cadena.Guarde y ejecute el código para observar la salida siguiente:
Start: Healthy Middle: Unhealthy End: UnhealthyAhora la cadena actualizada se captura y almacena correctamente.
Resumen
Esto es lo que ha aprendido sobre los parámetros de tipo de valor y de tipo de referencia hasta ahora:
- Las variables se pueden clasificar como tipos de valor y tipos de referencia.
- Los tipos de valor contienen directamente valores y los tipos de referencia almacenan la dirección del valor.
- Los métodos que usan argumentos de tipo de valor crean su propia copia de los valores.
- Los métodos que realizan cambios en un parámetro de matriz afectan a la matriz de entrada original.
- String es un tipo de referencia inmutable.
- Los métodos que realizan cambios en un parámetro de cadena no afectan a la cadena original.