Ejercicio: Usar parámetros de tipo de valor y referencia

Completado

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

  1. En el editor de Visual Studio Code, elimine cualquier código que haya de los ejercicios anteriores.

  2. 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, by c se pasan al Multiply mé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 ?

  3. Guarde y ejecute el código para observar la salida siguiente:

    inside Multiply method: 3 x 4 = 12
    global statement: 3 x 4 = 0
    

    Observe que el valor de c solo se modifica dentro del Multiply método . Fuera del método, c conserva su valor original.

Prueba de paso por referencia

  1. Elimine el código anterior del Editor de Visual Studio Code.

  2. 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 array inicializado para contener algunos valores enteros. Los valores se muestran mediante el PrintArray método . Se llama al método Clear en 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?

  3. Guarde y ejecute el código para observar la salida siguiente:

    1 2 3 4 5 
    0 0 0 0 0
    

    Observe que la matriz permanece modificada fuera del ámbito del Clear método. Esto sucede porque el Clear mé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.

  1. En el editor de Visual Studio Code, elimine cualquier código que haya de los ejercicios anteriores.

  2. 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}");
    }
    
  3. Guarde y ejecute el código para observar la salida siguiente:

    Start: Healthy
    Middle: Unhealthy
    End: Healthy
    

    Si el SetHealth mé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 SetHealth para usar la variable de estado global en su lugar.

  4. 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 status con el nuevo valor de cadena.

  5. Guarde y ejecute el código para observar la salida siguiente:

    Start: Healthy
    Middle: Unhealthy
    End: Unhealthy
    

    Ahora 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.