Ćwiczenie — używanie parametrów typu wartości i odwołania

Zakończone

W języku C#zmienne można podzielić na dwa główne typy, typy wartości i typy referencyjne. Te typy opisują sposób przechowywania wartości przez zmienne.

Typy wartości, takie jak int, , boolfloat, doubleichar, zawierają bezpośrednio wartości. Typy odwołań, takie jak string, array, i obiekty (takie jak wystąpienia Random), nie przechowują swoich wartości bezpośrednio. Zamiast tego typy odwołań przechowują adres, w którym jest przechowywana ich wartość.

Parametry przekazywane przez wartość i przekazywane przez odwołanie

Po przekazaniu argumentu do metody zmienne typu wartości mają wartości skopiowane do metody. Każda zmienna ma własną kopię wartości, więc oryginalna zmienna nie jest modyfikowana.

W przypadku typów referencyjnych adres wartości jest przekazywany do metody . Zmienna podana w metodzie odwołuje się do wartości pod tym adresem, więc operacje na tej zmiennej wpływają na wartość, do której odwołuje się druga.

Uwaga / Notatka

Należy pamiętać, że string jest to typ odwołania, ale jest niezmienny. Oznacza to, że po przypisaniu jej wartości nie można jej zmienić. W języku C#, gdy metody i operatory są używane do modyfikowania ciągu, zwracany wynik jest w rzeczywistości nowym obiektem ciągu.

W tym ćwiczeniu dowiesz się więcej na temat przekazywania argumentów typu referencyjnego i argumentów typu wartościowego do metod.

Test przekazywania wartości

  1. W edytorze programu Visual Studio Code usuń dowolny istniejący kod z poprzednich ćwiczeń.

  2. Wprowadź następujący kod w edytorze programu Visual Studio Code:

    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}");
    }
    

    Zmienne a, bi c są przekazywane do Multiply metody . Wartości zmiennych są drukowane podczas wykonywania metody i drukowane ponownie po zakończeniu metody.

    Liczby całkowite to typy wartościowe, których wartości są kopiowane podczas przekazywania do metod. Jak myślisz, jaki będzie wynik c?

  3. Zapisz i uruchom kod, aby obserwować następujące dane wyjściowe:

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

    Zwróć uwagę, że wartość c jest zmieniana tylko w ramach metody Multiply. Poza metodą c zachowuje oryginalną wartość.

Test przekazywania przez referencję

  1. Usuń poprzedni kod z edytora programu Visual Studio Code.

  2. Wprowadź następujący kod w edytorze programu Visual Studio Code:

    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;
        }
    }
    

    Kod rozpoczyna się od array, który został zainicjowany, aby zawierać pewne wartości całkowite. Wartości są wyświetlane przy użyciu PrintArray metody . Metoda Clear jest wywoływana w tablicy, a następnie tablica jest drukowana ponownie.

    Tablice są typami referencyjnymi. Typy referencyjne przechowują adres ich wartości w pamięci. Jak myślisz, jaki będzie wynik?

  3. Zapisz i uruchom kod, aby obserwować następujące dane wyjściowe:

    1 2 3 4 5 
    0 0 0 0 0
    

    Zwróć uwagę, że tablica pozostaje zmieniona poza zakresem metody Clear. Dzieje się tak, ponieważ Clear metoda zaktualizowała wartości przechowywane pod każdym adresem.

Testowanie przy użyciu ciągów

Wcześniej wiesz, że ciągi są niezmiennym typem. Mimo że ciąg jest typem odwołania, jego wartość nie może zostać zmieniona po przypisaniu, w przeciwieństwie do tablicy. Być może zauważysz to, jeśli użyto metod, takich jak string.Replace lub string.ToUpper. W tym zadaniu dowiesz się, jak naprawić typowy błąd występujący podczas pracy z ciągami.

  1. W edytorze programu Visual Studio Code usuń dowolny istniejący kod z poprzednich ćwiczeń.

  2. Wprowadź następujący kod w edytorze programu Visual Studio Code:

    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. Zapisz i uruchom kod, aby obserwować następujące dane wyjściowe:

    Start: Healthy
    Middle: Unhealthy
    End: Healthy
    

    SetHealth Jeśli metoda nie wyprowadzi stanu, być może przyjęto, że metoda nie jest wykonywana poprawnie. Zamiast tego utworzono nowy ciąg o wartości "Niezdrowy", który następnie został utracony w zakresie metody.

    Aby rozwiązać ten problem, możesz zmienić SetHealth , aby zamiast tego użyć globalnej zmiennej stanu.

  4. Zaktualizuj kod w następujący sposób:

    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}");
    }
    

    W tym kodzie zastąpisz zmienną globalną status nową wartością ciągu.

  5. Zapisz i uruchom kod, aby obserwować następujące dane wyjściowe:

    Start: Healthy
    Middle: Unhealthy
    End: Unhealthy
    

    Teraz zaktualizowany ciąg jest przechwytywany i przechowywany poprawnie.

Podsumowanie

Oto czego nauczyłeś się o typach wartości oraz typach referencyjnych do tej pory:

  • Zmienne można kategoryzować jako typy wartości i typy referencyjne.
  • Typy wartości zawierają bezpośrednio wartości, a typy referencyjne przechowują adres wartości.
  • Metody używające argumentów typu wartości tworzą własną kopię wartości.
  • Metody, które wykonują zmiany w parametrze tablicy, mają wpływ na oryginalną tablicę wejściową.
  • Ciąg jest niezmiennym typem odwołania.
  • Metody, które wykonują zmiany w parametrze ciągu, nie mają wpływu na oryginalny ciąg.